Factor out glyph rect function
parent
8fe9c579ef
commit
333a32208e
|
|
@ -385,6 +385,34 @@ pub const Face = struct {
|
|||
};
|
||||
}
|
||||
|
||||
/// Get a rect that represents the position and size of the loaded glyph.
|
||||
fn getGlyphSize(glyph: freetype.c.FT_GlyphSlot) font.face.RenderOptions.Constraint.GlyphSize {
|
||||
// If we're dealing with an outline glyph then we get the
|
||||
// outline's bounding box instead of using the built-in
|
||||
// metrics, since that's more precise and allows better
|
||||
// cell-fitting.
|
||||
if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
// Get the glyph's bounding box before we transform it at all.
|
||||
// We use this rather than the metrics, since it's more precise.
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&glyph.*.outline, &bbox);
|
||||
|
||||
return .{
|
||||
.x = f26dot6ToF64(bbox.xMin),
|
||||
.y = f26dot6ToF64(bbox.yMin),
|
||||
.width = f26dot6ToF64(bbox.xMax - bbox.xMin),
|
||||
.height = f26dot6ToF64(bbox.yMax - bbox.yMin),
|
||||
};
|
||||
}
|
||||
|
||||
return .{
|
||||
.x = f26dot6ToF64(glyph.*.metrics.horiBearingX),
|
||||
.y = f26dot6ToF64(glyph.*.metrics.horiBearingY - glyph.*.metrics.height),
|
||||
.width = f26dot6ToF64(glyph.*.metrics.width),
|
||||
.height = f26dot6ToF64(glyph.*.metrics.height),
|
||||
};
|
||||
}
|
||||
|
||||
/// Render a glyph using the glyph index. The rendered glyph is stored in the
|
||||
/// given texture atlas.
|
||||
pub fn renderGlyph(
|
||||
|
|
@ -403,37 +431,7 @@ pub const Face = struct {
|
|||
|
||||
// We get a rect that represents the position
|
||||
// and size of the glyph before any changes.
|
||||
const rect: struct {
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64,
|
||||
} = metrics: {
|
||||
// If we're dealing with an outline glyph then we get the
|
||||
// outline's bounding box instead of using the built-in
|
||||
// metrics, since that's more precise and allows better
|
||||
// cell-fitting.
|
||||
if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
// Get the glyph's bounding box before we transform it at all.
|
||||
// We use this rather than the metrics, since it's more precise.
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&glyph.*.outline, &bbox);
|
||||
|
||||
break :metrics .{
|
||||
.x = f26dot6ToF64(bbox.xMin),
|
||||
.y = f26dot6ToF64(bbox.yMin),
|
||||
.width = f26dot6ToF64(bbox.xMax - bbox.xMin),
|
||||
.height = f26dot6ToF64(bbox.yMax - bbox.yMin),
|
||||
};
|
||||
}
|
||||
|
||||
break :metrics .{
|
||||
.x = f26dot6ToF64(glyph.*.metrics.horiBearingX),
|
||||
.y = f26dot6ToF64(glyph.*.metrics.horiBearingY - glyph.*.metrics.height),
|
||||
.width = f26dot6ToF64(glyph.*.metrics.width),
|
||||
.height = f26dot6ToF64(glyph.*.metrics.height),
|
||||
};
|
||||
};
|
||||
const rect = getGlyphSize(glyph);
|
||||
|
||||
// If our glyph is smaller than a quarter pixel in either axis
|
||||
// then it has no outlines or they're too small to render.
|
||||
|
|
@ -988,21 +986,9 @@ pub const Face = struct {
|
|||
f26dot6ToF64(glyph.*.advance.x),
|
||||
max,
|
||||
);
|
||||
// We use the outline's bbox instead of the built-in
|
||||
// metrics for better accuracy (see renderGlyph()).
|
||||
const ymin, const ymax = metrics: {
|
||||
if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&glyph.*.outline, &bbox);
|
||||
break :metrics .{ bbox.yMin, bbox.yMax };
|
||||
}
|
||||
break :metrics .{
|
||||
glyph.*.metrics.horiBearingY - glyph.*.metrics.height,
|
||||
glyph.*.metrics.horiBearingY,
|
||||
};
|
||||
};
|
||||
top = @max(f26dot6ToF64(ymax), top);
|
||||
bottom = @min(f26dot6ToF64(ymin), bottom);
|
||||
const rect = getGlyphSize(glyph);
|
||||
top = @max(rect.y + rect.height, top);
|
||||
bottom = @min(rect.y, bottom);
|
||||
} else |_| {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1042,15 +1028,7 @@ pub const Face = struct {
|
|||
defer self.ft_mutex.unlock();
|
||||
if (face.getCharIndex('H')) |glyph_index| {
|
||||
if (face.loadGlyph(glyph_index, self.glyphLoadFlags(false))) {
|
||||
const glyph = face.handle.*.glyph;
|
||||
// We use the outline's bbox instead of the built-in
|
||||
// metrics for better accuracy (see renderGlyph()).
|
||||
if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&glyph.*.outline, &bbox);
|
||||
break :cap f26dot6ToF64(bbox.yMax - bbox.yMin);
|
||||
}
|
||||
break :cap f26dot6ToF64(glyph.*.metrics.height);
|
||||
break :cap getGlyphSize(face.handle.*.glyph).height;
|
||||
} else |_| {}
|
||||
}
|
||||
break :cap null;
|
||||
|
|
@ -1060,15 +1038,7 @@ pub const Face = struct {
|
|||
defer self.ft_mutex.unlock();
|
||||
if (face.getCharIndex('x')) |glyph_index| {
|
||||
if (face.loadGlyph(glyph_index, self.glyphLoadFlags(false))) {
|
||||
const glyph = face.handle.*.glyph;
|
||||
// We use the outline's bbox instead of the built-in
|
||||
// metrics for better accuracy (see renderGlyph()).
|
||||
if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&glyph.*.outline, &bbox);
|
||||
break :ex f26dot6ToF64(bbox.yMax - bbox.yMin);
|
||||
}
|
||||
break :ex f26dot6ToF64(glyph.*.metrics.height);
|
||||
break :ex getGlyphSize(face.handle.*.glyph).height;
|
||||
} else |_| {}
|
||||
}
|
||||
break :ex null;
|
||||
|
|
@ -1095,31 +1065,19 @@ pub const Face = struct {
|
|||
// This can sometimes happen if there's a CJK font that has been
|
||||
// patched with the nerd fonts patcher and it butchers the advance
|
||||
// values so the advance ends up half the width of the actual glyph.
|
||||
const ft_glyph_width = ft_glyph_width: {
|
||||
// We use the outline's bbox instead of the built-in
|
||||
// metrics for better accuracy (see renderGlyph()).
|
||||
if (ft_glyph.*.format == freetype.c.FT_GLYPH_FORMAT_OUTLINE) {
|
||||
var bbox: freetype.c.FT_BBox = undefined;
|
||||
_ = freetype.c.FT_Outline_Get_BBox(&ft_glyph.*.outline, &bbox);
|
||||
break :ft_glyph_width bbox.xMax - bbox.xMin;
|
||||
}
|
||||
break :ft_glyph_width ft_glyph.*.metrics.width;
|
||||
};
|
||||
if (ft_glyph_width > ft_glyph.*.advance.x) {
|
||||
const ft_glyph_width = getGlyphSize(ft_glyph).width;
|
||||
const advance = f26dot6ToF64(ft_glyph.*.advance.x);
|
||||
if (ft_glyph_width > advance) {
|
||||
var buf: [1024]u8 = undefined;
|
||||
const font_name = self.name(&buf) catch "<Error getting font name>";
|
||||
log.warn(
|
||||
"(getMetrics) Width of glyph '水' for font \"{s}\" is greater than its advance ({d} > {d}), discarding ic_width metric.",
|
||||
.{
|
||||
font_name,
|
||||
f26dot6ToF64(ft_glyph_width),
|
||||
f26dot6ToF64(ft_glyph.*.advance.x),
|
||||
},
|
||||
.{ font_name, ft_glyph_width, advance },
|
||||
);
|
||||
break :ic_width null;
|
||||
}
|
||||
|
||||
break :ic_width f26dot6ToF64(ft_glyph.*.advance.x);
|
||||
break :ic_width advance;
|
||||
};
|
||||
|
||||
return .{
|
||||
|
|
|
|||
Loading…
Reference in New Issue