summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2009-05-05 13:25:13 -0400
committerBehdad Esfahbod <behdad@behdad.org>2009-05-05 13:25:13 -0400
commit8afbf62147bca4db12e78426ea9c41b5e801c7ed (patch)
tree4e4f2803ce6c4401ed8814b3b4743280f8d054ed /pango
parent0bb5d464baab47bb7b6e9852a5c7932bdb2df018 (diff)
downloadpango-8afbf62147bca4db12e78426ea9c41b5e801c7ed.tar.gz
[GSUB] Implement ligature substitutions
Diffstat (limited to 'pango')
-rw-r--r--pango/opentype/Makefile.am2
-rw-r--r--pango/opentype/hb-ot-layout-gsub-private.h113
2 files changed, 93 insertions, 22 deletions
diff --git a/pango/opentype/Makefile.am b/pango/opentype/Makefile.am
index 40644c1a..e5ea114d 100644
--- a/pango/opentype/Makefile.am
+++ b/pango/opentype/Makefile.am
@@ -57,6 +57,8 @@ harfbuzz_dump_LDADD = \
$(libharfbuzz_1_la_LIBADD) \
libharfbuzz-1.la
+main_SOURCES = \
+ main.cc
main_LDADD = \
$(GLIB_LIBS)
diff --git a/pango/opentype/hb-ot-layout-gsub-private.h b/pango/opentype/hb-ot-layout-gsub-private.h
index 73950dcc..d1418232 100644
--- a/pango/opentype/hb-ot-layout-gsub-private.h
+++ b/pango/opentype/hb-ot-layout-gsub-private.h
@@ -44,7 +44,7 @@
hb_ot_layout_t *layout, \
hb_buffer_t *buffer, \
unsigned int context_length, \
- unsigned int nesting_level_left, \
+ unsigned int nesting_level_left HB_GNUC_UNUSED, \
unsigned int lookup_flag
#define SUBTABLE_SUBSTITUTE_ARGS \
layout, \
@@ -135,8 +135,6 @@ struct SingleSubst {
inline bool substitute (SUBTABLE_SUBSTITUTE_ARGS_DEF) const {
- HB_UNUSED (nesting_level_left);
-
if (HB_UNLIKELY (context_length < 1))
return false;
@@ -205,8 +203,6 @@ struct MultipleSubstFormat1 {
inline bool substitute (SUBTABLE_SUBSTITUTE_ARGS_DEF) const {
- HB_UNUSED (nesting_level_left);
-
if (HB_UNLIKELY (context_length < 1))
return false;
@@ -307,8 +303,6 @@ struct AlternateSubstFormat1 {
inline bool substitute (SUBTABLE_SUBSTITUTE_ARGS_DEF) const {
- HB_UNUSED (nesting_level_left);
-
if (HB_UNLIKELY (context_length < 1))
return false;
@@ -392,7 +386,77 @@ DEFINE_NULL (AlternateSubst, 2);
struct Ligature {
- /* TODO */
+
+ friend struct LigatureSet;
+
+ private:
+ DEFINE_ARRAY_TYPE (GlyphID, component, (compCount ? compCount - 1 : 0));
+
+ inline bool substitute_ligature (SUBTABLE_SUBSTITUTE_ARGS_DEF, bool is_mark) const {
+
+ unsigned int i, j;
+ unsigned int property;
+ unsigned int count = compCount;
+
+ if (HB_UNLIKELY (buffer->in_pos + count > buffer->in_length ||
+ context_length < count))
+ return false; /* Not enough glyphs in input or context */
+
+ for (i = 1, j = buffer->in_pos + 1; i < count; i++, j++) {
+ while (!_hb_ot_layout_check_glyph_property (layout, IN_ITEM (j), lookup_flag, &property)) {
+ if (HB_UNLIKELY (j + count - i == buffer->in_length))
+ return false;
+ j++;
+ }
+
+ if (!(property == HB_OT_LAYOUT_GLYPH_CLASS_MARK ||
+ property & LookupFlag::MarkAttachmentType))
+ is_mark = FALSE;
+
+ if (HB_LIKELY (IN_GLYPH(j) != (*this)[i - 1]))
+ return false;
+ }
+ if ( _hb_ot_layout_has_new_glyph_classes (layout) )
+ /* this is just a guess ... */
+ hb_ot_layout_set_glyph_class (layout, ligGlyph,
+ is_mark ? HB_OT_LAYOUT_GLYPH_CLASS_MARK
+ : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
+
+ if (j == buffer->in_pos + i) /* No input glyphs skipped */
+ /* We don't use a new ligature ID if there are no skipped
+ glyphs and the ligature already has an ID. */
+ _hb_buffer_add_output_glyph_ids (buffer, i,
+ 1, &ligGlyph,
+ 0xFFFF,
+ IN_LIGID (buffer->in_pos) ?
+ 0xFFFF : _hb_buffer_allocate_ligid (buffer));
+ else
+ {
+ unsigned int lig_id = _hb_buffer_allocate_ligid (buffer);
+ _hb_buffer_add_output_glyph (buffer, ligGlyph, 0xFFFF, lig_id);
+
+ /* Now we must do a second loop to copy the skipped glyphs to
+ `out' and assign component values to it. We start with the
+ glyph after the first component. Glyphs between component
+ i and i+1 belong to component i. Together with the lig_id
+ value it is later possible to check whether a specific
+ component value really belongs to a given ligature. */
+
+ for ( i = 0; i < count - 1; i++ )
+ {
+ while (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM(), lookup_flag, &property))
+ _hb_buffer_add_output_glyph (buffer, IN_CURGLYPH(), i, lig_id);
+
+ (buffer->in_pos)++;
+ }
+
+ /* XXX We should possibly reassign lig_id and component for any
+ * components of a previous ligature that s now being removed as part of
+ * this ligature. */
+ }
+
+ return true;
+ }
private:
GlyphID ligGlyph; /* GlyphID of ligature to substitute */
@@ -404,7 +468,23 @@ struct Ligature {
DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
struct LigatureSet {
- /* TODO */
+
+ friend struct LigatureSubstFormat1;
+
+ private:
+ DEFINE_OFFSET_ARRAY_TYPE (Ligature, ligature, ligatureCount);
+
+ inline bool substitute_ligature (SUBTABLE_SUBSTITUTE_ARGS_DEF, bool is_mark) const {
+
+ unsigned int num_ligs = get_len ();
+ for (unsigned int i = 0; i < num_ligs; i++) {
+ const Ligature &lig = (*this)[i];
+ if (lig.substitute_ligature (SUBTABLE_SUBSTITUTE_ARGS, is_mark))
+ return true;
+ }
+
+ return false;
+ }
private:
USHORT ligatureCount; /* Number of Ligature tables */
@@ -427,8 +507,6 @@ struct LigatureSubstFormat1 {
inline bool substitute (SUBTABLE_SUBSTITUTE_ARGS_DEF) const {
- HB_UNUSED (nesting_level_left);
-
unsigned int property;
if (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM (), lookup_flag, &property))
return false;
@@ -437,20 +515,11 @@ struct LigatureSubstFormat1 {
unsigned int index = get_glyph_coverage (glyph_id);
- const LigatureSet &lig_set = (*this)[index];
-
bool first_is_mark = (property == HB_OT_LAYOUT_GLYPH_CLASS_MARK ||
property & LookupFlag::MarkAttachmentType);
- unsigned int num_sets = get_len ();
- for (unsigned int i = 0; i < num_sets; i++) {
-
- const LigatureSet &lig_set = (*this)[i];
-
-
- }
-
- return false;
+ const LigatureSet &lig_set = (*this)[index];
+ return lig_set.substitute_ligature (SUBTABLE_SUBSTITUTE_ARGS, first_is_mark);
}
private: