FontBLF: Store Sizes, Styles, and Other Metrics #113432
|
@ -1344,6 +1344,176 @@ static void blf_font_fill(FontBLF *font)
|
|||
font->buf_info.col_init[3] = 0;
|
||||
}
|
||||
|
||||
/* Note that the data the following function creates is not yet used.
|
||||
* But do not remove it as it will be used in the near future - Harley */
|
||||
static void blf_font_metrics(FT_Face face, FontMetrics *metrics)
|
||||
{
|
||||
/* Members with non-zero defaults. */
|
||||
metrics->weight = 400;
|
||||
metrics->width = 1.0f;
|
||||
metrics->spacing = 1.0f;
|
||||
|
||||
TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
|
||||
if (os2_table) {
|
||||
/* The default (resting) font weight. */
|
||||
if (os2_table->usWeightClass >= 1 && os2_table->usWeightClass <= 1000) {
|
||||
metrics->weight = short(os2_table->usWeightClass);
|
||||
}
|
||||
|
||||
/* Width value is one of integers 1-9 with known values. */
|
||||
if (os2_table->usWidthClass >= 1 && os2_table->usWidthClass <= 9) {
|
||||
switch (os2_table->usWidthClass) {
|
||||
case 1:
|
||||
metrics->width = 0.5f;
|
||||
break;
|
||||
case 2:
|
||||
metrics->width = 0.625f;
|
||||
break;
|
||||
case 3:
|
||||
metrics->width = 0.75f;
|
||||
break;
|
||||
case 4:
|
||||
metrics->width = 0.875f;
|
||||
break;
|
||||
case 5:
|
||||
metrics->width = 1.0f;
|
||||
break;
|
||||
case 6:
|
||||
metrics->width = 1.125f;
|
||||
break;
|
||||
case 7:
|
||||
metrics->width = 1.25f;
|
||||
break;
|
||||
case 8:
|
||||
metrics->width = 1.5f;
|
||||
break;
|
||||
case 9:
|
||||
metrics->width = 2.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
metrics->strikeout_position = short(os2_table->yStrikeoutPosition);
|
||||
metrics->strikeout_thickness = short(os2_table->yStrikeoutSize);
|
||||
metrics->subscript_size = short(os2_table->ySubscriptYSize);
|
||||
metrics->subscript_xoffset = short(os2_table->ySubscriptXOffset);
|
||||
metrics->subscript_yoffset = short(os2_table->ySubscriptYOffset);
|
||||
metrics->superscript_size = short(os2_table->ySuperscriptYSize);
|
||||
metrics->superscript_xoffset = short(os2_table->ySuperscriptXOffset);
|
||||
metrics->superscript_yoffset = short(os2_table->ySuperscriptYOffset);
|
||||
metrics->family_class = short(os2_table->sFamilyClass);
|
||||
metrics->selection_flags = short(os2_table->fsSelection);
|
||||
metrics->first_charindex = short(os2_table->usFirstCharIndex);
|
||||
metrics->last_charindex = short(os2_table->usLastCharIndex);
|
||||
if (os2_table->version > 1) {
|
||||
metrics->cap_height = short(os2_table->sCapHeight);
|
||||
metrics->x_height = short(os2_table->sxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/* The Post table usually contains a slant value, but in counter-clockwise degrees. */
|
||||
TT_Postscript *post_table = (TT_Postscript *)FT_Get_Sfnt_Table(face, FT_SFNT_POST);
|
||||
if (post_table) {
|
||||
if (post_table->italicAngle != 0) {
|
||||
metrics->slant = float(post_table->italicAngle) / -65536.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Metrics copied from those gathered by FreeType. */
|
||||
metrics->units_per_EM = short(face->units_per_EM);
|
||||
metrics->ascender = short(face->ascender);
|
||||
metrics->descender = short(face->descender);
|
||||
metrics->line_height = short(face->height);
|
||||
metrics->max_advance_width = short(face->max_advance_width);
|
||||
metrics->max_advance_height = short(face->max_advance_height);
|
||||
metrics->underline_position = short(face->underline_position);
|
||||
metrics->underline_thickness = short(face->underline_thickness);
|
||||
metrics->num_glyphs = int(face->num_glyphs);
|
||||
metrics->bounding_box.xmin = int(face->bbox.xMin);
|
||||
metrics->bounding_box.xmax = int(face->bbox.xMax);
|
||||
metrics->bounding_box.ymin = int(face->bbox.yMin);
|
||||
metrics->bounding_box.ymax = int(face->bbox.yMax);
|
||||
|
||||
if (metrics->cap_height == 0) {
|
||||
/* Calculate or guess cap height if it is not set in the font. */
|
||||
FT_UInt gi = FT_Get_Char_Index(face, uint('H'));
|
||||
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
|
||||
metrics->cap_height = short(face->glyph->metrics.height);
|
||||
}
|
||||
else {
|
||||
metrics->cap_height = short(float(metrics->units_per_EM) * 0.7f);
|
||||
}
|
||||
}
|
||||
|
||||
if (metrics->x_height == 0) {
|
||||
/* Calculate or guess x-height if it is not set in the font. */
|
||||
FT_UInt gi = FT_Get_Char_Index(face, uint('x'));
|
||||
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
|
||||
metrics->x_height = short(face->glyph->metrics.height);
|
||||
}
|
||||
else {
|
||||
metrics->x_height = short(float(metrics->units_per_EM) * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
FT_UInt gi = FT_Get_Char_Index(face, uint('o'));
|
||||
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
|
||||
metrics->o_proportion = float(face->glyph->metrics.width) / float(face->glyph->metrics.height);
|
||||
}
|
||||
|
||||
if (metrics->ascender == 0) {
|
||||
/* Set a sane value for ascender if not set in the font. */
|
||||
metrics->ascender = short(float(metrics->units_per_EM) * 0.8f);
|
||||
}
|
||||
|
||||
if (metrics->descender == 0) {
|
||||
/* Set a sane value for descender if not set in the font. */
|
||||
metrics->descender = metrics->ascender - metrics->units_per_EM;
|
||||
}
|
||||
|
||||
if (metrics->weight == 400 && face->style_flags & FT_STYLE_FLAG_BOLD) {
|
||||
/* Normal weight yet this is an bold font, so set a sane weight value. */
|
||||
metrics->weight = 700;
|
||||
}
|
||||
|
||||
if (metrics->slant == 0.0f && face->style_flags & FT_STYLE_FLAG_ITALIC) {
|
||||
/* No slant yet this is an italic font, so set a sane slant value. */
|
||||
metrics->slant = 8.0f;
|
||||
}
|
||||
|
||||
if (metrics->underline_position == 0) {
|
||||
metrics->underline_position = short(float(metrics->units_per_EM) * -0.2f);
|
||||
}
|
||||
|
||||
if (metrics->underline_thickness == 0) {
|
||||
metrics->underline_thickness = short(float(metrics->units_per_EM) * 0.07f);
|
||||
}
|
||||
|
||||
if (metrics->strikeout_position == 0) {
|
||||
metrics->strikeout_position = short(float(metrics->x_height) * 0.6f);
|
||||
}
|
||||
|
||||
if (metrics->strikeout_thickness == 0) {
|
||||
metrics->strikeout_thickness = metrics->underline_thickness;
|
||||
}
|
||||
|
||||
if (metrics->subscript_size == 0) {
|
||||
metrics->subscript_size = short(float(metrics->units_per_EM) * 0.6f);
|
||||
}
|
||||
|
||||
if (metrics->subscript_yoffset == 0) {
|
||||
metrics->subscript_yoffset = short(float(metrics->units_per_EM) * 0.075f);
|
||||
}
|
||||
|
||||
if (metrics->superscript_size == 0) {
|
||||
metrics->superscript_size = short(float(metrics->units_per_EM) * 0.6f);
|
||||
}
|
||||
|
||||
if (metrics->superscript_yoffset == 0) {
|
||||
metrics->superscript_yoffset = short(float(metrics->units_per_EM) * 0.35f);
|
||||
}
|
||||
}
|
||||
|
||||
bool blf_ensure_face(FontBLF *font)
|
||||
{
|
||||
if (font->face) {
|
||||
|
@ -1431,6 +1601,9 @@ bool blf_ensure_face(FontBLF *font)
|
|||
FT_Get_MM_Var(font->face, &(font->variations));
|
||||
}
|
||||
|
||||
blf_ensure_size(font);
|
||||
blf_font_metrics(font->face, &font->metrics);
|
||||
|
||||
/* Save TrueType table with bits to quickly test most unicode block coverage. */
|
||||
TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2);
|
||||
if (os2_table) {
|
||||
|
|
|
@ -209,6 +209,75 @@ typedef struct FontBufInfoBLF {
|
|||
|
||||
} FontBufInfoBLF;
|
||||
|
||||
typedef struct FontMetrics {
|
||||
/** This font's default weight, 100-900, 400 is normal. */
|
||||
short weight;
|
||||
/** This font's default width, 1 is normal, 2 is twice as wide. */
|
||||
float width;
|
||||
/** This font's slant in clockwise degrees, 0 being upright. */
|
||||
float slant;
|
||||
/** This font's default spacing, 1 is normal. */
|
||||
float spacing;
|
||||
|
||||
/** Number of font units in an EM square. 2048, 1024, 1000 are typical. */
|
||||
short units_per_EM; /* */
|
||||
/** Design classification from OS/2 sFamilyClass. */
|
||||
short family_class;
|
||||
/** Style classification from OS/2 fsSelection. */
|
||||
short selection_flags;
|
||||
/** Total number of glyphs in the font. */
|
||||
int num_glyphs;
|
||||
/** Minimum Unicode index, typically 0x0020. */
|
||||
short first_charindex;
|
||||
/** Maximum Unicode index, or 0xFFFF if greater than. */
|
||||
short last_charindex;
|
||||
|
||||
/**
|
||||
* Bounds that can contain every glyph in the font when in default positions. Can be used for
|
||||
* maximum ascender, minimum descender. Can be out by a pixel when hinting. Does not change with
|
||||
* variation axis changes. */
|
||||
rcti bounding_box;
|
||||
/**
|
||||
* Positive number of font units from baseline to top of typical capitals. Can be slightly more
|
||||
* than cap height when head serifs, terminals, or apexes extend above cap line. */
|
||||
short ascender;
|
||||
/** Negative (!) number of font units from baseline to bottom of letters like "gjpqy". */
|
||||
short descender;
|
||||
/** Positive number of font units between consecutive baselines. */
|
||||
short line_height;
|
||||
/** Font units from baseline to lowercase mean line, typically to top of "x". */
|
||||
short x_height;
|
||||
/** Font units from baseline to top of capital letters, specifically "H". */
|
||||
short cap_height;
|
||||
/** Ratio width to heigh of lowercase "O". Reliable indication of font proportion. */
|
||||
float o_proportion;
|
||||
/** Font unit maximum horizontal advance for all glyphs in font. Can help with wrapping. */
|
||||
short max_advance_width;
|
||||
/** As above but only for vertical layout fonts, otherwise is set to line_height value. */
|
||||
short max_advance_height;
|
||||
|
||||
/** Negative (!) number of font units below baseline to center (!) of underlining stem. */
|
||||
short underline_position;
|
||||
/** thickness of the underline in font units. */
|
||||
short underline_thickness;
|
||||
/** Positive number of font units above baseline to the top (!) of strikeout stroke. */
|
||||
short strikeout_position;
|
||||
/** thickness of the strikeout line in font units. */
|
||||
short strikeout_thickness;
|
||||
/** EM size font units of recommended subscript letters. */
|
||||
short subscript_size;
|
||||
/** Horizontal offset before first subscript character, typically 0. */
|
||||
short subscript_xoffset;
|
||||
/** Postive number of font units above baseline for subscript characters. */
|
||||
short subscript_yoffset;
|
||||
/** EM size font units of recommended superscript letters. */
|
||||
short superscript_size;
|
||||
/** Horizontal offset before first superscript character, typically 0. */
|
||||
short superscript_xoffset;
|
||||
/** Postive (!) number of font units below baseline for subscript characters. */
|
||||
short superscript_yoffset;
|
||||
} FontMetrics;
|
||||
|
||||
typedef struct FontBLF {
|
||||
/** Full path to font file or NULL if from memory. */
|
||||
char *filepath;
|
||||
|
@ -307,6 +376,9 @@ typedef struct FontBLF {
|
|||
/** Copy of the font->face->face_flags, in case we don't have a face loaded. */
|
||||
FT_Long face_flags;
|
||||
|
||||
/** Details about the font's design and style and sizes (in unsized font units). */
|
||||
FontMetrics metrics;
|
||||
|
||||
/** Data for buffer usage (drawing into a texture buffer) */
|
||||
FontBufInfoBLF buf_info;
|
||||
|
||||
|
|
Loading…
Reference in New Issue