From 00b2653ac3b927f93ac350dbe1d3711790a50119 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Sat, 16 Mar 2019 16:27:33 -0700 Subject: [PATCH] add components transformation --- src/hb-ot-glyf-table.hh | 44 +++++++++++++++++++++++++++++++++++-- src/hb-ot-var-gvar-table.hh | 31 +++++++++++++++----------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index a494bbebb..2793fbaa3 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -172,6 +172,44 @@ struct glyf return size; } + void transform_point (float &x, float &y) const + { + int tx, ty; + const HBINT8 *p = &StructAfter (glyphIndex); + if (flags & ARG_1_AND_2_ARE_WORDS) + { + tx = *(const HBINT16 *)p; + p += HBINT16::static_size; + ty = *(const HBINT16 *)p; + p += HBINT16::static_size; + } + else + { + tx = *p++; + ty = *p++; + } + if (!(flags & ARGS_ARE_XY_VALUES)) tx = ty = 0; /* TODO: anchor point unsupported for now */ + + if (flags & WE_HAVE_A_SCALE) + { + float scale = ((const F2DOT14*)p)->to_float (); + x *= scale; + y *= scale; + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + x *= ((const F2DOT14*)p)[0].to_float (); + y *= ((const F2DOT14*)p)[1].to_float (); + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + float x_ = x * ((const F2DOT14*)p)[0].to_float () + y * ((const F2DOT14*)p)[1].to_float (); + y = x * ((const F2DOT14*)p)[2].to_float () + y * ((const F2DOT14*)p)[3].to_float (); + x = x_; + } + if (tx | ty) { x += tx; y += ty; } + } + struct Iterator { const char *glyph_start; @@ -341,7 +379,8 @@ struct glyf uint8_t flag = points_[i].flag; if (coord_setter.is_short (flag)) { - if (unlikely (!checker.in_range (p))) return false; + if (unlikely (!checker.in_range (p))) + return false; if (coord_setter.is_same (flag)) v += *p++; else @@ -349,9 +388,10 @@ struct glyf } else { - if (unlikely (!checker.in_range ((const HBUINT16 *)p))) return false; if (!coord_setter.is_same (flag)) { + if (unlikely (!checker.in_range ((const HBUINT16 *)p))) + return false; v += *(const HBINT16 *)p; p += HBINT16::static_size; } diff --git a/src/hb-ot-var-gvar-table.hh b/src/hb-ot-var-gvar-table.hh index 5b5a7884b..43841274d 100644 --- a/src/hb-ot-var-gvar-table.hh +++ b/src/hb-ot-var-gvar-table.hh @@ -119,9 +119,9 @@ struct TupleVarHeader unsigned int get_data_size () const { return varDataSize; } - bool has_peak () const { return (tupleIndex & TuppleIndex::EmbeddedPeakTuple) != 0; } - bool has_intermediate () const { return (tupleIndex & TuppleIndex::IntermediateRegion) != 0; } - bool has_private_points () const { return (tupleIndex & TuppleIndex::PrivatePointNumbers) != 0; } + bool has_peak () const { return (tupleIndex & TuppleIndex::EmbeddedPeakTuple); } + bool has_intermediate () const { return (tupleIndex & TuppleIndex::IntermediateRegion); } + bool has_private_points () const { return (tupleIndex & TuppleIndex::PrivatePointNumbers); } unsigned int get_index () const { return (tupleIndex & TuppleIndex::TupleIndexMask); } protected: @@ -144,7 +144,7 @@ struct TupleVarHeader struct TupleVarCount : HBUINT16 { - bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers) != 0; } + bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); } unsigned int get_count () const { return (*this) & CountMask; } protected: @@ -249,7 +249,7 @@ struct GlyphVarData if (!check.in_range (p)) return false; uint16_t count = *p++; - if ((count & POINTS_ARE_WORDS) != 0) + if (count & POINTS_ARE_WORDS) { if (!check.in_range (p)) return false; count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++; @@ -263,7 +263,7 @@ struct GlyphVarData uint16_t j; uint8_t control = *p++; uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1; - if ((control & POINTS_ARE_WORDS) != 0) + if (control & POINTS_ARE_WORDS) { for (j = 0; j < run_count && i < count; j++, i++) { @@ -304,12 +304,12 @@ struct GlyphVarData uint16_t j; uint8_t control = *p++; uint16_t run_count = (control & DELTA_RUN_COUNT_MASK) + 1; - if ((control & DELTAS_ARE_ZERO) != 0) + if (control & DELTAS_ARE_ZERO) { for (j = 0; j < run_count && i < count; j++, i++) deltas[i] = 0; } - else if ((control & DELTAS_ARE_WORDS) != 0) + else if (control & DELTAS_ARE_WORDS) { for (j = 0; j < run_count && i < count; j++, i++) { @@ -518,6 +518,7 @@ struct gvar if (unlikely (coord_count != gvar_table->axisCount)) return false; const GlyphVarData *var_data = gvar_table->get_glyph_var_data (glyph); + if (var_data == &Null(GlyphVarData)) return true; hb_vector_t shared_indices; GlyphVarData::tuple_iterator_t iterator; if (!GlyphVarData::get_tuple_iterator (var_data, @@ -624,10 +625,13 @@ struct gvar if (!glyf_accel.get_composite (glyph, &composite)) return true; /* simple glyph */ do { - /* TODO: support component scale/transformation */ - if (((composite.current->flags & glyf::CompositeGlyphHeader::USE_MY_METRICS) != 0) && - !get_var_metrics (composite.current->glyphIndex, coords, coord_count, phantoms)) - return false; + if (composite.current->flags & glyf::CompositeGlyphHeader::USE_MY_METRICS) + { + if (!get_var_metrics (composite.current->glyphIndex, coords, coord_count, phantoms)) + return false; + for (unsigned int j = 0; j < phantoms.length; j++) + composite.current->transform_point (phantoms[j].x, phantoms[j].y); + } } while (composite.move_to_next()); return true; } @@ -677,7 +681,8 @@ struct gvar if (!get_bounds_var (composite.current->glyphIndex, coords, coord_count, comp_bounds)) return false; - /* TODO: support component scale/transformation */ + composite.current->transform_point (comp_bounds.min.x, comp_bounds.min.y); + composite.current->transform_point (comp_bounds.max.x, comp_bounds.max.y); bounds._union (comp_bounds); } while (composite.move_to_next()); return true;