[ot-font] Start adding vertical support

This commit is contained in:
Behdad Esfahbod 2014-09-25 13:04:08 +03:00
parent 22f0de5025
commit d41b809e9d
3 changed files with 100 additions and 55 deletions

View File

@ -39,10 +39,15 @@
struct hb_ot_font_t struct hb_ot_font_t
{ {
unsigned int num_glyphs; unsigned int num_glyphs;
unsigned int num_hmetrics; unsigned int num_hmetrics;
const OT::hmtx *hmtx; const OT::hmtx *hmtx;
hb_blob_t *hmtx_blob; hb_blob_t *hmtx_blob;
unsigned int num_vmetrics;
const OT::vmtx *vmtx;
hb_blob_t *vmtx_blob;
const OT::CmapSubtable *cmap; const OT::CmapSubtable *cmap;
const OT::CmapSubtable *cmap_uvs; const OT::CmapSubtable *cmap_uvs;
hb_blob_t *cmap_blob; hb_blob_t *cmap_blob;
@ -59,21 +64,41 @@ _hb_ot_font_create (hb_font_t *font)
ot_font->num_glyphs = font->face->get_num_glyphs (); ot_font->num_glyphs = font->face->get_num_glyphs ();
/* Setup horizontal metrics. */
{ {
hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea)); hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob); const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
ot_font->num_hmetrics = hhea->numberOfHMetrics; ot_font->num_hmetrics = hhea->numberOfMetrics;
hb_blob_destroy (hhea_blob); hb_blob_destroy (hhea_blob);
ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
if (unlikely (!ot_font->num_hmetrics ||
2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
{
hb_blob_destroy (ot_font->hmtx_blob);
free (ot_font);
return NULL;
}
ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
} }
ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
if (unlikely (!ot_font->num_hmetrics || /* Setup vertical metrics. */
2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
{ {
hb_blob_destroy (ot_font->hmtx_blob); hb_blob_t *vhea_blob = OT::Sanitizer<OT::vhea>::sanitize (font->face->reference_table (HB_OT_TAG_vhea));
free (ot_font); const OT::vhea *vhea = OT::Sanitizer<OT::vhea>::lock_instance (vhea_blob);
return NULL; ot_font->num_vmetrics = vhea->numberOfMetrics;
hb_blob_destroy (vhea_blob);
ot_font->vmtx_blob = OT::Sanitizer<OT::vmtx>::sanitize (font->face->reference_table (HB_TAG('v','m','t','x')));
if (unlikely (!ot_font->num_vmetrics ||
2 * (ot_font->num_vmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->vmtx_blob)))
{
hb_blob_destroy (ot_font->vmtx_blob);
free (ot_font);
return NULL;
}
ot_font->vmtx = OT::Sanitizer<OT::vmtx>::lock_instance (ot_font->vmtx_blob);
} }
ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap)); ot_font->cmap_blob = OT::Sanitizer<OT::cmap>::sanitize (font->face->reference_table (HB_OT_TAG_cmap));
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob); const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (ot_font->cmap_blob);
@ -109,6 +134,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
{ {
hb_blob_destroy (ot_font->cmap_blob); hb_blob_destroy (ot_font->cmap_blob);
hb_blob_destroy (ot_font->hmtx_blob); hb_blob_destroy (ot_font->hmtx_blob);
hb_blob_destroy (ot_font->vmtx_blob);
free (ot_font); free (ot_font);
} }
@ -149,12 +175,12 @@ hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
if (unlikely (glyph >= ot_font->num_glyphs)) if (unlikely (glyph >= ot_font->num_glyphs))
return 0; /* Maybe better to return notdef's advance instead? */ return 0;
if (glyph >= ot_font->num_hmetrics) if (glyph >= ot_font->num_hmetrics)
glyph = ot_font->num_hmetrics - 1; glyph = ot_font->num_hmetrics - 1;
return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth); return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advance);
} }
static hb_position_t static hb_position_t
@ -163,8 +189,15 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
hb_codepoint_t glyph, hb_codepoint_t glyph,
void *user_data HB_UNUSED) void *user_data HB_UNUSED)
{ {
/* TODO */ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
return 0;
if (unlikely (glyph >= ot_font->num_glyphs))
return 0;
if (glyph >= ot_font->num_vmetrics)
glyph = ot_font->num_vmetrics - 1;
return font->em_scale_y (-ot_font->vmtx->longHorMetric[glyph].advance);
} }
static hb_bool_t static hb_bool_t

View File

@ -35,14 +35,17 @@ namespace OT {
/* /*
* hhea -- The Horizontal Header Table * hhea -- The Horizontal Header Table
* vhea -- The Vertical Header Table
*/ */
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a') #define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
struct hhea struct _hea
{ {
static const hb_tag_t tableTag = HB_OT_TAG_hhea; static const hb_tag_t hheaTag = HB_OT_TAG_hhea;
static const hb_tag_t vheaTag = HB_OT_TAG_vhea;
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -51,45 +54,45 @@ struct hhea
public: public:
FixedVersion version; /* 0x00010000u for version 1.0. */ FixedVersion version; /* 0x00010000u for version 1.0. */
FWORD ascender; /* Typographic ascent. <a FWORD ascender; /* Typographic ascent. */
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html"> FWORD descender; /* Typographic descent. */
* (Distance from baseline of highest FWORD lineGap; /* Typographic line gap. */
* ascender)</a> */ UFWORD advanceMax; /* Maximum advance width/height value in
FWORD descender; /* Typographic descent. <a * metrics table. */
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html"> FWORD minLeadingBearing; /* Minimum left/top sidebearing value in
* (Distance from baseline of lowest * metrics table. */
* descender)</a> */ FWORD minTrailingBearing; /* Minimum right/bottom sidebearing value;
FWORD lineGap; /* Typographic line gap. Negative
* LineGap values are treated as zero
* in Windows 3.1, System 6, and
* System 7. */
UFWORD advanceWidthMax; /* Maximum advance width value in
* 'hmtx' table. */
FWORD minLeftSideBearing; /* Minimum left sidebearing value in
* 'hmtx' table. */
FWORD minRightSideBearing; /* Minimum right sidebearing value;
* calculated as Min(aw - lsb - * calculated as Min(aw - lsb -
* (xMax - xMin)). */ * (xMax - xMin)) for horizontal. */
FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */ FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)),
* vertical: minLeadingBearing+(yMax-yMin). */
SHORT caretSlopeRise; /* Used to calculate the slope of the SHORT caretSlopeRise; /* Used to calculate the slope of the
* cursor (rise/run); 1 for vertical. */ * cursor (rise/run); 1 for vertical caret,
SHORT caretSlopeRun; /* 0 for vertical. */ * 0 for horizontal.*/
SHORT caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */
SHORT caretOffset; /* The amount by which a slanted SHORT caretOffset; /* The amount by which a slanted
* highlight on a glyph needs * highlight on a glyph needs
* to be shifted to produce the * to be shifted to produce the
* best appearance. Set to 0 for * best appearance. Set to 0 for
* non--slanted fonts */ * non-slanted fonts. */
SHORT reserved1; /* set to 0 */ SHORT reserved1; /* Set to 0. */
SHORT reserved2; /* set to 0 */ SHORT reserved2; /* Set to 0. */
SHORT reserved3; /* set to 0 */ SHORT reserved3; /* Set to 0. */
SHORT reserved4; /* set to 0 */ SHORT reserved4; /* Set to 0. */
SHORT metricDataFormat; /* 0 for current format. */ SHORT metricDataFormat; /* 0 for current format. */
USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx' USHORT numberOfMetrics; /* Number of LongMetric entries in metric
* table */ * table. */
public: public:
DEFINE_SIZE_STATIC (36); DEFINE_SIZE_STATIC (36);
}; };
struct hhea : _hea {
static const hb_tag_t tableTag = HB_OT_TAG_hhea;
};
struct vhea : _hea {
static const hb_tag_t tableTag = HB_OT_TAG_vhea;
};
} /* namespace OT */ } /* namespace OT */

View File

@ -35,22 +35,25 @@ namespace OT {
/* /*
* hmtx -- The Horizontal Metrics Table * hmtx -- The Horizontal Metrics Table
* vmtx -- The Vertical Metrics Table
*/ */
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
struct LongHorMetric struct LongMetric
{ {
USHORT advanceWidth; USHORT advance; /* Advance width/height. */
SHORT lsb; SHORT lsb; /* Leading (left/top) side bearing. */
public: public:
DEFINE_SIZE_STATIC (4); DEFINE_SIZE_STATIC (4);
}; };
struct hmtx struct _mtx
{ {
static const hb_tag_t tableTag = HB_OT_TAG_hmtx; static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx;
static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx;
inline bool sanitize (hb_sanitize_context_t *c) { inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -60,7 +63,7 @@ struct hmtx
} }
public: public:
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side LongMetric longHorMetric[VAR]; /* Paired advance width and leading
* bearing values for each glyph. The * bearing values for each glyph. The
* value numOfHMetrics comes from * value numOfHMetrics comes from
* the 'hhea' table. If the font is * the 'hhea' table. If the font is
@ -68,23 +71,29 @@ struct hmtx
* be in the array, but that entry is * be in the array, but that entry is
* required. The last entry applies to * required. The last entry applies to
* all subsequent glyphs. */ * all subsequent glyphs. */
SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed SHORT leadingBearingX[VAR]; /* Here the advance is assumed
* to be the same as the advanceWidth * to be the same as the advance
* for the last entry above. The * for the last entry above. The
* number of entries in this array is * number of entries in this array is
* derived from numGlyphs (from 'maxp' * derived from numGlyphs (from 'maxp'
* table) minus numberOfHMetrics. This * table) minus numberOfLongMetrics.
* generally is used with a run of * This generally is used with a run
* monospaced glyphs (e.g., Kanji * of monospaced glyphs (e.g., Kanji
* fonts or Courier fonts). Only one * fonts or Courier fonts). Only one
* run is allowed and it must be at * run is allowed and it must be at
* the end. This allows a monospaced * the end. This allows a monospaced
* font to vary the left side bearing * font to vary the side bearing
* values for each glyph. */ * values for each glyph. */
public: public:
DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX); DEFINE_SIZE_ARRAY2 (0, longHorMetric, leadingBearingX);
}; };
struct hmtx : _mtx {
static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
};
struct vmtx : _mtx {
static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
};
} /* namespace OT */ } /* namespace OT */