[aat] Implement trak logic (#816)
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index b061f11..06282e2 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -263,6 +263,13 @@
{
static const hb_tag_t tableTag = HB_AAT_TAG_kerx;
+ inline bool apply (hb_aat_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ /* TODO */
+ return_trace (false);
+ }
+
struct SubTableWrapper
{
enum coverage_flags_t {
diff --git a/src/hb-aat-layout-private.hh b/src/hb-aat-layout-private.hh
index c1c607a..ce75c8e 100644
--- a/src/hb-aat-layout-private.hh
+++ b/src/hb-aat-layout-private.hh
@@ -37,4 +37,7 @@
HB_INTERNAL void
hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer);
+HB_INTERNAL void
+hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer);
+
#endif /* HB_AAT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 6dbd05a..a5dc3ff 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -1,6 +1,6 @@
/*
- * Copyright © 2018 Google, Inc.
* Copyright © 2018 Ebrahim Byagowi
+ * Copyright © 2018 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -45,10 +45,15 @@
return_trace (c->check_struct (this));
}
+ inline float get_value (const void *base, unsigned int index) const
+ {
+ return (base+values)[index];
+ }
+
protected:
Fixed track; /* Track value for this record. */
HBUINT16 trackNameID; /* The 'name' table index for this track */
- OffsetTo<UnsizedArrayOf<Fixed> >
+ OffsetTo<UnsizedArrayOf<HBINT16> >
values; /* Offset from start of tracking table to
* per-size tracking values for this track. */
@@ -61,15 +66,48 @@
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
+ /* TODO */
return_trace (c->check_struct (this));
}
+ inline float get_tracking (const void *base, float ptem) const
+ {
+ /* CoreText points are CSS pixels (96 per inch),
+ * NOT typographic points (72 per inch).
+ *
+ * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+ */
+ float csspx = ptem * 96.f / 72.f;
+ Fixed fixed_size;
+ fixed_size.set_float (csspx);
+
+ // TODO: Make indexing work and use only an entry with zero track
+ const TrackTableEntry trackTableEntry = trackTable[0];
+
+ unsigned int size_index;
+ for (size_index = 0; size_index < nSizes; ++size_index)
+ if ((base+sizeTable)[size_index] >= fixed_size)
+ break;
+
+ // We don't attempt to extrapolate to larger or smaller values
+ if (size_index == nSizes)
+ return trackTableEntry.get_value (base, nSizes - 1);
+ if (size_index == 0 || (base+sizeTable)[size_index] == fixed_size)
+ return trackTableEntry.get_value (base, size_index);
+
+ float s0 = (base+sizeTable)[size_index - 1].to_float ();
+ float s1 = (base+sizeTable)[size_index].to_float ();
+ float t = (csspx - s0) / (s1 - s0);
+ return t * trackTableEntry.get_value (base, size_index) +
+ (1.0 - t) * trackTableEntry.get_value (base, size_index - 1);
+ }
+
protected:
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
HBUINT16 nSizes; /* Number of point sizes included in this table. */
LOffsetTo<UnsizedArrayOf<Fixed> >
sizeTable;
- TrackTableEntry trackTable[VAR];/* Array[nSizes] of size values. */
+ UnsizedArrayOf<TrackTableEntry> trackTable;/* Array[nSizes] of size values. */
public:
DEFINE_SIZE_ARRAY (8, trackTable);
@@ -82,9 +120,43 @@
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
+ /* TODO */
return_trace (c->check_struct (this));
}
+ inline bool apply (hb_aat_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ const float ptem = c->font->ptem;
+ if (ptem > 0.f)
+ {
+ hb_buffer_t *buffer = c->buffer;
+ if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction))
+ {
+ const TrackData trackData = this+horizOffset;
+ float tracking = trackData.get_tracking (this, ptem);
+ hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
+ foreach_grapheme (buffer, start, end)
+ {
+ buffer->pos[start].x_advance += advance_to_add;
+ buffer->pos[end].x_advance += advance_to_add;
+ }
+ }
+ else
+ {
+ const TrackData trackData = this+vertOffset;
+ float tracking = trackData.get_tracking (this, ptem);
+ hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
+ foreach_grapheme (buffer, start, end)
+ {
+ buffer->pos[start].y_advance += advance_to_add;
+ buffer->pos[end].y_advance += advance_to_add;
+ }
+ }
+ }
+ return_trace (false);
+ }
+
protected:
FixedVersion<> version; /* Version of the tracking table--currently
* 0x00010000u for version 1.0. */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 3b967c6..2b67bf3 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -55,6 +55,40 @@
return morx;
}
+static inline const AAT::kerx&
+_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+ {
+ if (blob)
+ *blob = hb_blob_get_empty ();
+ return OT::Null(AAT::kerx);
+ }
+ hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+ /* XXX this doesn't call set_num_glyphs on sanitizer. */
+ const AAT::kerx& kerx = *(layout->kerx.get ());
+ if (blob)
+ *blob = layout->kerx.blob;
+ return kerx;
+}
+
+static inline const AAT::trak&
+_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+ {
+ if (blob)
+ *blob = hb_blob_get_empty ();
+ return OT::Null(AAT::trak);
+ }
+ hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+ /* XXX this doesn't call set_num_glyphs on sanitizer. */
+ const AAT::trak& trak = *(layout->trak.get ());
+ if (blob)
+ *blob = layout->trak.blob;
+ return trak;
+}
+
static inline void
_hb_aat_layout_create (hb_face_t *face)
{
@@ -78,3 +112,15 @@
AAT::hb_aat_apply_context_t c (font, buffer, blob);
morx.apply (&c);
}
+
+void
+hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer)
+{
+ hb_blob_t *blob;
+ const AAT::kerx& kerx = _get_kerx (font->face, &blob);
+ const AAT::trak& trak = _get_trak (font->face, &blob);
+
+ AAT::hb_aat_apply_context_t c (font, buffer, blob);
+ kerx.apply (&c);
+ trak.apply (&c);
+}
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index f5c20bc..e465788 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -692,8 +692,8 @@
/* 32-bit signed fixed-point number (16.16). */
struct Fixed: HBINT32
{
- //inline float to_float (void) const { return ???; }
- //inline void set_float (float f) { v.set (f * ???); }
+ inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
+ inline void set_float (float f) { v.set (round (f * 65536.0)); }
public:
DEFINE_SIZE_STATIC (4);
};
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 0c3bcbc..ce1f6a8 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -363,6 +363,28 @@
return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
}
+
+/* Loop over grapheme. Based on foreach_cluster(). */
+#define foreach_grapheme(buffer, start, end) \
+ for (unsigned int \
+ _count = buffer->len, \
+ start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
+ start < _count; \
+ start = end, end = _next_grapheme (buffer, start))
+
+static inline unsigned int
+_next_grapheme (hb_buffer_t *buffer, unsigned int start)
+{
+ hb_glyph_info_t *info = buffer->info;
+ unsigned int count = buffer->len;
+
+ while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
+ ;
+
+ return start;
+}
+
+
#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
static inline bool
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 4cf6c72..b92ba05 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -65,6 +65,8 @@
layout->fvar.init (face);
layout->avar.init (face);
layout->morx.init (face);
+ layout->kerx.init (face);
+ layout->trak.init (face);
{
/*
@@ -215,6 +217,8 @@
layout->fvar.fini ();
layout->avar.fini ();
layout->morx.fini ();
+ layout->kerx.fini ();
+ layout->trak.fini ();
free (layout);
}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index d9ba0f6..d2d8012 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -787,6 +787,8 @@
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
+
+ //hb_aat_layout_position (c->font, c->buffer);
}
static inline void