[kerx] Implement Format4 'ankr'-based mark attachment
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 11 Oct 2018 05:14:18 +0000 (01:14 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 11 Oct 2018 05:17:33 +0000 (01:17 -0400)
Tested with Kannada MN:

$ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0CCD,0C95,0CD6
[kn_ka.vattu=0+230|kn_ai_length_mark=1@326,0+607]

src/hb-aat-layout-common.hh
src/hb-aat-layout-kerx-table.hh
src/hb-aat-layout.cc
src/hb-ot-layout-gpos-table.hh

index dada9c7..78de04f 100644 (file)
@@ -531,6 +531,7 @@ struct hb_aat_apply_context_t :
   hb_buffer_t *buffer;
   hb_sanitize_context_t sanitizer;
   const ankr &ankr_table;
+  const char *ankr_end;
 
   /* Unused. For debug tracing only. */
   unsigned int lookup_index;
@@ -540,9 +541,12 @@ struct hb_aat_apply_context_t :
                                 hb_font_t *font_,
                                 hb_buffer_t *buffer_,
                                 hb_blob_t *table,
-                                const ankr &ankr_table_ = Null(ankr)) :
+                                const ankr &ankr_table_ = Null(ankr),
+                                const char *ankr_end_ = nullptr) :
                plan (plan_), font (font_), face (font->face), buffer (buffer_),
-               sanitizer (), ankr_table (ankr_table_), lookup_index (0), debug_depth (0)
+               sanitizer (),
+               ankr_table (ankr_table_), ankr_end (ankr_end_),
+               lookup_index (0), debug_depth (0)
   {
     sanitizer.init (table);
     sanitizer.set_num_glyphs (face->get_num_glyphs ());
index c109d00..019efd5 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "hb-open-type.hh"
 #include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-kern-table.hh"
 
 /*
@@ -362,9 +363,22 @@ struct KerxSubTableFormat4
            const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex];
            if (!c->sanitizer.check_array (data, 2))
              return false;
-           HB_UNUSED unsigned int markAnchorPoint = *data++;
-           HB_UNUSED unsigned int currAnchorPoint = *data++;
-           /* TODO */
+           unsigned int markAnchorPoint = *data++;
+           unsigned int currAnchorPoint = *data++;
+           const Anchor markAnchor = c->ankr_table.get_anchor (c->buffer->info[mark].codepoint,
+                                                               markAnchorPoint,
+                                                               c->face->get_num_glyphs (),
+                                                               c->ankr_end);
+           const Anchor currAnchor = c->ankr_table.get_anchor (c->buffer->cur ().codepoint,
+                                                               currAnchorPoint,
+                                                               c->face->get_num_glyphs (),
+                                                               c->ankr_end);
+           hb_glyph_position_t &o = buffer->cur_pos();
+           o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate);
+           o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate);
+           o.attach_type() = ATTACH_TYPE_MARK;
+           o.attach_chain() = (int) mark - (int) buffer->idx;
+           buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
          }
          break;
 
index 47462ad..73ab06d 100644 (file)
@@ -69,10 +69,18 @@ _get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
   return kerx;
 }
 static inline const AAT::ankr&
-_get_ankr (hb_face_t *face)
+_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::ankr);
-  return *(hb_ot_face_data (face)->ankr.get ());
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  {
+    if (blob)
+      *blob = hb_blob_get_empty ();
+    return Null(AAT::ankr);
+  }
+  const AAT::ankr& ankr = *(hb_ot_face_data (face)->ankr.get ());
+  if (blob)
+    *blob = hb_ot_face_data (face)->ankr.get_blob ();
+  return ankr;
 }
 
 
@@ -109,6 +117,10 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan,
   hb_blob_t *blob;
   const AAT::kerx& kerx = _get_kerx (font->face, &blob);
 
-  AAT::hb_aat_apply_context_t c (plan, font, buffer, blob, _get_ankr (font->face));
+  hb_blob_t *ankr_blob;
+  const AAT::ankr& ankr = _get_ankr (font->face, &ankr_blob);
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, blob,
+                                ankr, ankr_blob->data + ankr_blob->length);
   kerx.apply (&c);
 }
index 1a96609..746c246 100644 (file)
@@ -1755,10 +1755,6 @@ template <typename context_t>
 struct GPOS_accelerator_t : GPOS::accelerator_t {};
 
 
-#undef attach_chain
-#undef attach_type
-
-
 } /* namespace OT */