[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-08-11 Thread Behdad Esfahbod
 TODO   |4 +
 src/hb-ot-shape-complex-arabic.cc  |  110 +
 src/hb-ot-shape-complex-indic.cc   |1 
 src/hb-ot-shape-complex-misc.cc|   12 ++--
 src/hb-ot-shape-complex-private.hh |   15 -
 src/hb-ot-shape-fallback.cc|   22 ++-
 src/hb-ot-shape.cc |3 +
 7 files changed, 123 insertions(+), 44 deletions(-)

New commits:
commit 9f9f04c2229227bb0712166e824157bbbf5cef80
Author: Behdad Esfahbod beh...@behdad.org
Date:   Sat Aug 11 18:34:13 2012 -0400

[OT] Unbreak Thai shaping and fallback Arabic shaping

The merger of normalizer and glyph-mapping broke shapers that
modified text stream.  Unbreak them by adding a new preprocess_text
shaping stage that happens before normalizing/cmap and disallow
setup_mask modification of actual text.

diff --git a/src/hb-ot-shape-complex-arabic.cc 
b/src/hb-ot-shape-complex-arabic.cc
index e0db41c..e1a2791 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -274,12 +274,8 @@ arabic_fallback_shape (hb_font_t *font, hb_buffer_t 
*buffer)
 }
 
 static void
-setup_masks_arabic (const hb_ot_shape_plan_t *plan,
-   hb_buffer_t  *buffer,
-   hb_font_t*font)
+arabic_joining (hb_buffer_t *buffer)
 {
-  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) 
plan-data;
-
   unsigned int count = buffer-len;
   unsigned int prev = 0, state = 0;
 
@@ -305,14 +301,37 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
 state = entry-next_state;
   }
 
-  if (likely (!arabic_plan-do_fallback)) {
-/* Has OpenType tables */
-for (unsigned int i = 0; i  count; i++)
-  buffer-info[i].mask |= 
arabic_plan-mask_array[buffer-info[i].arabic_shaping_action()];
-  } else
+  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+}
+
+static void
+preprocess_text_arabic (const hb_ot_shape_plan_t *plan,
+   hb_buffer_t  *buffer,
+   hb_font_t*font)
+{
+  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) 
plan-data;
+
+  if (unlikely (arabic_plan-do_fallback))
+  {
+arabic_joining (buffer);
 arabic_fallback_shape (font, buffer);
+  }
+}
 
-  HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+static void
+setup_masks_arabic (const hb_ot_shape_plan_t *plan,
+   hb_buffer_t  *buffer,
+   hb_font_t*font)
+{
+  const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) 
plan-data;
+
+  if (likely (!arabic_plan-do_fallback))
+  {
+arabic_joining (buffer);
+unsigned int count = buffer-len;
+for (unsigned int i = 0; i  count; i++)
+  buffer-info[i].mask |= 
arabic_plan-mask_array[buffer-info[i].arabic_shaping_action()];
+  }
 }
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
@@ -322,6 +341,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
   NULL, /* override_features */
   data_create_arabic,
   data_destroy_arabic,
+  preprocess_text_arabic,
   NULL, /* normalization_preference */
   setup_masks_arabic,
   true, /* zero_width_attached_marks */
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 4f9a5af..6fbd5c8 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -1134,6 +1134,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
   override_features_indic,
   data_create_indic,
   data_destroy_indic,
+  NULL, /* preprocess_text */
   NULL, /* normalization_preference */
   setup_masks_indic,
   false, /* zero_width_attached_marks */
diff --git a/src/hb-ot-shape-complex-misc.cc b/src/hb-ot-shape-complex-misc.cc
index 4f1dd5b..13bc22b 100644
--- a/src/hb-ot-shape-complex-misc.cc
+++ b/src/hb-ot-shape-complex-misc.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2010  Google, Inc.
+ * Copyright © 2010,2012  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -90,6 +90,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
   NULL, /* override_features */
   NULL, /* data_create */
   NULL, /* data_destroy */
+  NULL, /* preprocess_text */
   normalization_preference_default,
   NULL, /* setup_masks */
   true, /* zero_width_attached_marks */
@@ -99,9 +100,9 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
 /* Thai / Lao shaper */
 
 static void
-setup_masks_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t  *buffer,
- hb_font_t*font HB_UNUSED)
+preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t  *buffer,
+ hb_font_t*font HB_UNUSED)
 {
   /* The following is NOT specified in the MS OT Thai spec, however, it seems
* to be what Uniscribe and 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-08-02 Thread Behdad Esfahbod
 src/hb-ot-layout-gpos-table.hh   |2 
 src/hb-ot-layout-gsub-table.hh   |5 -
 src/hb-ot-layout-gsubgpos-private.hh |   10 +-
 src/hb-ot-layout-private.hh  |3 
 src/hb-ot-layout.cc  |   34 +++
 src/hb-ot-map-private.hh |   85 +++--
 src/hb-ot-map.cc |   18 +--
 src/hb-ot-shape-complex-indic-private.hh |   16 ---
 src/hb-ot-shape-complex-indic.cc |  149 ++-
 9 files changed, 184 insertions(+), 138 deletions(-)

New commits:
commit 610e5e8f713bb2a68939b72cb2b801a7aaede4f9
Author: Behdad Esfahbod beh...@behdad.org
Date:   Thu Aug 2 05:27:46 2012 -0400

[Indic] Streamline feature would_apply()

Comes with some 10% speedup for Devanagari even!

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 2ba0f76..5e3c967 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -42,6 +42,38 @@ struct hb_ot_map_t
 
   public:
 
+  struct feature_map_t {
+hb_tag_t tag; /* should be first for our bsearch to work */
+unsigned int index[2]; /* GSUB/GPOS */
+unsigned int stage[2]; /* GSUB/GPOS */
+unsigned int shift;
+hb_mask_t mask;
+hb_mask_t _1_mask; /* mask for value=1, for quick access */
+
+static int cmp (const feature_map_t *a, const feature_map_t *b)
+{ return a-tag  b-tag ? -1 : a-tag  b-tag ? 1 : 0; }
+  };
+
+  struct lookup_map_t {
+unsigned int index;
+hb_mask_t mask;
+
+static int cmp (const lookup_map_t *a, const lookup_map_t *b)
+{ return a-index  b-index ? -1 : a-index  b-index ? 1 : 0; }
+  };
+
+  typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, 
hb_buffer_t *buffer, void *user_data);
+  typedef struct {
+pause_func_t func;
+void *user_data;
+  } pause_callback_t;
+
+  struct pause_map_t {
+unsigned int num_lookups; /* Cumulative */
+pause_callback_t callback;
+  };
+
+
   hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); }
 
   typedef void (*gsub_pause_func_t) (const hb_ot_map_t *map, hb_face_t *face, 
hb_buffer_t *buffer, void *user_data);
@@ -60,11 +92,30 @@ struct hb_ot_map_t
 return map ? map-_1_mask : 0;
   }
 
-  inline hb_mask_t get_feature_index (unsigned int table_index, hb_tag_t 
feature_tag) const {
+  inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t 
feature_tag) const {
 const feature_map_t *map = features.bsearch (feature_tag);
 return map ? map-index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
   }
 
+  inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t 
feature_tag) const {
+const feature_map_t *map = features.bsearch (feature_tag);
+return map ? map-stage[table_index] : (unsigned int) -1;
+  }
+
+  inline void get_stage_lookups (unsigned int table_index, unsigned int stage,
+const struct lookup_map_t **plookups, unsigned 
int *lookup_count) const {
+if (unlikely (stage == (unsigned int) -1)) {
+  *plookups = NULL;
+  *lookup_count = 0;
+  return;
+}
+assert (stage = pauses[table_index].len);
+unsigned int start = stage ? pauses[table_index][stage - 1].num_lookups : 
0;
+unsigned int end   = stage  pauses[table_index].len ? 
pauses[table_index][stage].num_lookups : lookups[table_index].len;
+*plookups = lookups[table_index][start];
+*lookup_count = end - start;
+  }
+
   inline hb_tag_t get_chosen_script (unsigned int table_index) const
   { return chosen_script[table_index]; }
 
@@ -80,38 +131,8 @@ struct hb_ot_map_t
 pauses[1].finish ();
   }
 
-  private:
-
-  struct feature_map_t {
-hb_tag_t tag; /* should be first for our bsearch to work */
-unsigned int index[2]; /* GSUB/GPOS */
-unsigned int stage[2]; /* GSUB/GPOS */
-unsigned int shift;
-hb_mask_t mask;
-hb_mask_t _1_mask; /* mask for value=1, for quick access */
-
-static int cmp (const feature_map_t *a, const feature_map_t *b)
-{ return a-tag  b-tag ? -1 : a-tag  b-tag ? 1 : 0; }
-  };
-
-  struct lookup_map_t {
-unsigned int index;
-hb_mask_t mask;
-
-static int cmp (const lookup_map_t *a, const lookup_map_t *b)
-{ return a-index  b-index ? -1 : a-index  b-index ? 1 : 0; }
-  };
 
-  typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, 
hb_buffer_t *buffer, void *user_data);
-  typedef struct {
-pause_func_t func;
-void *user_data;
-  } pause_callback_t;
-
-  struct pause_map_t {
-unsigned int num_lookups; /* Cumulative */
-pause_callback_t callback;
-  };
+  private:
 
   HB_INTERNAL void add_lookups (hb_face_t*face,
unsigned int  table_index,
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 20e8e6f..ae0cb61 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -89,7 +89,8 @@ void hb_ot_map_t::substitute (hb_face_t *face, hb_buffer_t 
*buffer) const
 
 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-07-29 Thread Behdad Esfahbod
 src/hb-old.cc  
|   12 +-
 src/hb-ot-layout-gsub-table.hh 
|   18 +++---
 src/hb-shape-plan.cc   
|2 -
 src/test.cc
|2 -
 
test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/MANIFEST 
   |1 
 
test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/ligature-components.txt
 |   18 ++
 6 files changed, 38 insertions(+), 15 deletions(-)

New commits:
commit ef6e9cec3399e4f63f4b662abd77cf6d4683e8a3
Author: Behdad Esfahbod beh...@behdad.org
Date:   Sun Jul 29 21:35:22 2012 -0400

Fixup bb0e4ba3e9c5a407fc5d73c914e429d24d336380

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index f9f9f3d..a478ba5 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -115,7 +115,7 @@ hb_shape_plan_get_empty (void)
   static const hb_shape_plan_t _hb_shape_plan_nil = {
 HB_OBJECT_HEADER_STATIC,
 
-false, /* default_shaper_list */
+true, /* default_shaper_list */
 NULL, /* face */
 _HB_BUFFER_PROPS_DEFAULT, /* props */
 
commit cb3d34063154bf164c61eeba41c6166b0bd304fb
Author: Behdad Esfahbod beh...@behdad.org
Date:   Sun Jul 29 20:37:38 2012 -0400

[GSUB] Don't set new lig_id on mark ligatures

If two marks form a ligature, retain their previous lig_id, such that
the mark ligature can attach to ligature components...

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=676343

In fact, I noticed that we should not let ligatures form between glyphs
coming from different components of a previous ligature.  For example,
if the sequence is: LAM,SHADDA,LAM,FATHA,HEH, the LAM,LAM,HEH form a
ligature, putting SHADDA and FATHA next to eachother.  However, it would
be wrong to ligate them.  Uniscribe has this bug also.

diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 03244b5..a74f707 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -499,11 +499,20 @@ struct Ligature
   if (likely (c-buffer-info[skippy_iter.idx].codepoint != component[i])) 
return TRACE_RETURN (false);
 }
 
-unsigned int klass = first_was_mark  found_non_mark ? 
HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE : 0;
+bool is_a_mark_ligature = first_was_mark  !found_non_mark;
+
+unsigned int klass = is_a_mark_ligature ? 0 : 
HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
+
+/* If it's a mark ligature, we should leave the lig_id / lig_comp alone 
such that
+ * the resulting mark ligature has the opportunity to attach to ligature 
components
+ * of it's base later on.  See for example:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=676343
+ */
 
 /* Allocate new ligature id */
-unsigned int lig_id = allocate_lig_id (c-buffer);
-set_lig_props (c-buffer-cur(), lig_id, 0);
+unsigned int lig_id = is_a_mark_ligature ? 0 : allocate_lig_id (c-buffer);
+if (!is_a_mark_ligature)
+  set_lig_props (c-buffer-cur(), lig_id, 0);
 
 if (skippy_iter.idx  c-buffer-idx + count) /* No input glyphs skipped */
 {
@@ -526,7 +535,8 @@ struct Ligature
   {
while (c-should_mark_skip_current_glyph ())
{
- set_lig_props (c-buffer-cur(),  lig_id, i);
+ if (!is_a_mark_ligature)
+   set_lig_props (c-buffer-cur(),  lig_id, i);
  c-buffer-next_glyph ();
}
 
commit 97a201becf936f62046914b568e5763e27ee936e
Author: Behdad Esfahbod beh...@behdad.org
Date:   Sun Jul 29 20:31:36 2012 -0400

Add Arabic tests for mark ligature component attachments

diff --git 
a/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/MANIFEST
 
b/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/MANIFEST
index 242b2a1..c71d035 100644
--- 
a/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/MANIFEST
+++ 
b/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/MANIFEST
@@ -2,5 +2,6 @@ lam-alef.txt
 language-arabic.txt
 language-persian.txt
 language-urdu.txt
+ligature-components.txt
 ligature-diacritics.txt
 mark-skipping.txt
diff --git 
a/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/ligature-components.txt
 
b/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/ligature-components.txt
new file mode 100644
index 000..0d4d47f
--- /dev/null
+++ 
b/test/shaping/texts/in-tree/shaper-arabic/script-arabic/misc/diacritics/ligature-components.txt
@@ -0,0 +1,18 @@
+لّله
+لَّله
+لَّله
+للّه
+للَّه
+للَّه
+للهّ
+للهَّ
+للهَّ
+لّلَه
+لَلّه
+لّلهَ
+لَلهّ
+للّهَ
+للَهّ
+لّلّهَ
+لّلَّه
+لَّلّه
commit 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-05-09 Thread Behdad Esfahbod
 test/shaping/Makefile.am  |2 
 test/shaping/hb-diff-ngrams   |5 +
 test/shaping/hb-diff-stat |5 +
 test/shaping/hb_test_tools.py |  174 +++---
 4 files changed, 177 insertions(+), 9 deletions(-)

New commits:
commit 2214a03900d32710573a1b05c7665195b3129761
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed May 9 09:54:54 2012 +0200

Add hb-diff-ngrams

diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index 81c9991..4fb762c 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -13,6 +13,7 @@ EXTRA_DIST += \
hb-diff \
hb-diff-colorize \
hb-diff-filter-failures \
+   hb-diff-ngrams \
hb-diff-stat \
hb-manifest-read \
hb-manifest-update \
diff --git a/test/shaping/hb-diff-ngrams b/test/shaping/hb-diff-ngrams
new file mode 100755
index 000..a496447
--- /dev/null
+++ b/test/shaping/hb-diff-ngrams
@@ -0,0 +1,5 @@
+#!/usr/bin/python
+
+from hb_test_tools import *
+
+UtilMains.process_multiple_files (DiffSinks.print_ngrams)
diff --git a/test/shaping/hb_test_tools.py b/test/shaping/hb_test_tools.py
index a38f067..3ff75b8 100644
--- a/test/shaping/hb_test_tools.py
+++ b/test/shaping/hb_test_tools.py
@@ -155,12 +155,60 @@ class DiffFilters:
if not DiffHelpers.test_passed (lines):
for l in lines: yield l
 
+class Stat:
+
+   def __init__ (self):
+   self.count = 0
+   self.freq = 0
+
+   def add (self, test):
+   self.count += 1
+   self.freq += test.freq
+
+class Stats:
+
+   def __init__ (self):
+   self.passed = Stat ()
+   self.failed = Stat ()
+   self.total  = Stat ()
+
+   def add (self, test):
+   self.total.add (test)
+   if test.passed:
+   self.passed.add (test)
+   else:
+   self.failed.add (test)
+
+   def mean (self):
+   return float (self.passed.count) / self.total.count
+
+   def variance (self):
+   return (float (self.passed.count) / self.total.count) * \
+  (float (self.failed.count) / self.total.count)
+
+   def stddev (self):
+   return self.variance () ** .5
+
+   def zscore (self, population):
+   Calculate the standard score.
+  Population is the Stats for population.
+  Self is Stats for sample.
+  Returns larger absolute value if sample is highly unlikely 
to be random.
+  Anything outside of -3..+3 is very unlikely to be random.
+  See: http://en.wikipedia.org/wiki/Standard_score;
+
+   return (self.mean () - population.mean ()) / population.stddev 
()
+
+
+
+
 class DiffSinks:
 
@staticmethod
def print_stat (f):
passed = 0
failed = 0
+   # XXX port to Stats, but that would really slow us down here
for key, lines in DiffHelpers.separate_test_cases (f):
if DiffHelpers.test_passed (lines):
passed += 1
@@ -172,21 +220,34 @@ class DiffSinks:
@staticmethod
def print_ngrams (f, ns=(1,2,3)):
gens = tuple (Ngram.generator (n) for n in ns)
+   allstats = Stats ()
+   allgrams = {}
for key, lines in DiffHelpers.separate_test_cases (f):
test = Test (lines)
-   unicodes = test.unicodes
-   del test
+   allstats.add (test)
 
for gen in gens:
-   print Printing %d-grams: % gen.n
-   for ngram in gen (unicodes):
-   print ngram
+   for ngram in gen (test.unicodes):
+   if ngram not in allgrams:
+   allgrams[ngram] = Stats ()
+   allgrams[ngram].add (test)
+
+   importantgrams = {}
+   for ngram, stats in allgrams.iteritems ():
+   if stats.failed.count = 30: # for statistical reasons
+   importantgrams[ngram] = stats
+   allgrams = importantgrams
+   del importantgrams
+
+   for ngram, stats in allgrams.iteritems ():
+   print zscore: %9f failed: %6d passed: %6d ngram: %s 
% (stats.zscore (allstats), stats.failed.count, stats.passed.count, ','.join 
(U+%04X % u for u in ngram))
 
 
 
 class Test:
 
def __init__ (self, lines):
+   self.freq = 1
self.passed = True
self.identifier = None
self.text = None
commit 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-04-12 Thread Behdad Esfahbod
 configure.ac   |6 ++--
 src/Makefile.am|   11 +++-
 src/hb-blob.h  |6 +++-
 src/hb-buffer.h|4 +++
 src/hb-common.h|   10 +--
 src/hb-fallback-shape-private.hh   |9 +++
 src/hb-fallback-shape.cc   |9 +++
 src/hb-font.h  |4 +++
 src/hb-ft.cc   |2 +
 src/hb-ft.h|2 -
 src/hb-glib.h  |1 
 src/hb-gobject.h   |1 
 src/hb-graphite2-private.hh|   42 +
 src/hb-graphite2.cc|5 +--
 src/hb-graphite2.h |   10 +--
 src/hb-icu.h   |1 
 src/hb-ot-layout-common-private.hh |2 -
 src/hb-ot-layout-gdef-table.hh |2 -
 src/hb-ot-layout-gpos-table.hh |5 +--
 src/hb-ot-layout-gsub-table.hh |2 -
 src/hb-ot-layout-private.hh|2 -
 src/hb-ot-layout.h |8 +++---
 src/hb-ot-shape-private.hh |8 --
 src/hb-ot-shape.cc |   11 +++-
 src/hb-ot-shape.h  |   47 -
 src/hb-ot-tag.h|6 +++-
 src/hb-ot.h|3 +-
 src/hb-private.hh  |5 +++
 src/hb-shape.cc|   24 +++---
 src/hb-shape.h |5 +++
 src/hb-unicode.h   |4 +++
 src/hb-uniscribe-private.hh|   42 +
 src/hb-uniscribe.cc|9 +++
 src/hb-uniscribe.h |   10 ---
 src/hb-version.h.in|4 +++
 src/hb.h   |2 +
 util/helper-cairo.hh   |5 ++-
 util/options.hh|9 ++-
 util/view-cairo.cc |   31 
 util/view-cairo.hh |1 
 40 files changed, 222 insertions(+), 148 deletions(-)

New commits:
commit 69b84a8f6c789726815261c2e86692de7a65d6e8
Author: Behdad Esfahbod beh...@behdad.org
Date:   Thu Apr 12 15:50:40 2012 -0400

Fix hb-view surface size calc for vertical text

For some reason it doesn't quite work with IranianNastaliq, but
that looks like a font issue.

diff --git a/util/helper-cairo.hh b/util/helper-cairo.hh
index 5edfc3a..bc3fe1d 100644
--- a/util/helper-cairo.hh
+++ b/util/helper-cairo.hh
@@ -64,8 +64,9 @@ struct helper_cairo_line_t {
   g_free (utf8);
   }
 
-  double get_width (void) {
-return glyphs[num_glyphs].x;
+  void get_advance (double *x_advance, double *y_advance) {
+*x_advance = glyphs[num_glyphs].x;
+*y_advance = glyphs[num_glyphs].y;
   }
 };
 
diff --git a/util/options.hh b/util/options.hh
index 165e7a1..da95017 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -48,6 +48,13 @@
 #include glib.h
 #include glib/gprintf.h
 
+#undef MIN
+template typename Type static inline Type MIN (const Type a, const Type b) 
{ return a  b ? a : b; }
+
+#undef MAX
+template typename Type static inline Type MAX (const Type a, const Type b) 
{ return a  b ? a : b; }
+
+
 void fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN;
 
 
diff --git a/util/view-cairo.cc b/util/view-cairo.cc
index f766a4f..ce578ed 100644
--- a/util/view-cairo.cc
+++ b/util/view-cairo.cc
@@ -38,6 +38,7 @@ view_cairo_t::consume_line (hb_buffer_t  *buffer,
const char   *text,
unsigned int  text_len)
 {
+  direction = hb_buffer_get_direction (buffer);
   helper_cairo_line_t l;
   helper_cairo_line_from_buffer (l, buffer, text, text_len, scale);
   g_array_append_val (lines, l);
@@ -63,14 +64,17 @@ view_cairo_t::get_surface_size (cairo_scaled_font_t 
*scaled_font,
 
   cairo_scaled_font_extents (scaled_font, font_extents);
 
-  *h = font_extents.ascent
- + font_extents.descent
- + ((int) lines-len - 1) * (font_extents.height + line_space);
-  *w = 0;
+  bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+  (vertical ? *w : *h) = (int) lines-len * (font_extents.height + line_space) 
- line_space;
+  (vertical ? *h : *w) = 0;
   for (unsigned int i = 0; i  lines-len; i++) {
 helper_cairo_line_t line = g_array_index (lines, helper_cairo_line_t, i);
-double line_width = line.get_width ();
-*w = MAX (*w, line_width);
+double x_advance, y_advance;
+line.get_advance (x_advance, y_advance);
+if (vertical)
+  *h =  MAX (*h, y_advance);
+else
+  *w =  MAX (*w, x_advance);
   }
 
   *w += margin.l + margin.r;
@@ -97,17 +101,26 @@ view_cairo_t::draw (cairo_t *cr)
 {
   cairo_save (cr);
 
+  bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+  int v = vertical ? 1 : 0;
+  int h = vertical ? 0 : 1;
   cairo_font_extents_t font_extents;
   cairo_font_extents (cr, font_extents);
   cairo_translate (cr, margin.l, 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-03-07 Thread Behdad Esfahbod
 src/hb-common.cc   |6 +
 src/hb-common.h|  203 +++--
 src/hb-glib.cc |   11 +-
 src/hb-ot-shape-complex-private.hh |9 +
 4 files changed, 129 insertions(+), 100 deletions(-)

New commits:
commit f91136cb528e298651c4a8a8a1d6dc54136e09ce
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Mar 7 12:56:22 2012 -0500

Route three Unicode 6.1 scripts through Indic shaper

diff --git a/src/hb-ot-shape-complex-private.hh 
b/src/hb-ot-shape-complex-private.hh
index 652d90a..52d0523 100644
--- a/src/hb-ot-shape-complex-private.hh
+++ b/src/hb-ot-shape-complex-private.hh
@@ -79,7 +79,9 @@ hb_ot_shape_complex_categorize (const hb_segment_properties_t 
*props)
 /* Note:
  *
  * These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, but 
according
- * to Martin Hosken do not require complex shaping.
+ * to Martin Hosken and Jonathan Kew do not require complex shaping.
+ *
+ * TODO We should automate figuring out which scripts do not need complex 
shaping
  *
  * TODO We currently keep data for these scripts in our indic table.  Need 
to fix the
  * generator to not do that.
@@ -113,6 +115,7 @@ hb_ot_shape_complex_categorize (const 
hb_segment_properties_t *props)
 case HB_SCRIPT_BALINESE:
 case HB_SCRIPT_BENGALI:
 case HB_SCRIPT_BUGINESE:
+case HB_SCRIPT_CHAKMA:
 case HB_SCRIPT_CHAM:
 case HB_SCRIPT_DEVANAGARI:
 case HB_SCRIPT_GUJARATI:
@@ -127,9 +130,11 @@ hb_ot_shape_complex_categorize (const 
hb_segment_properties_t *props)
 case HB_SCRIPT_NEW_TAI_LUE:
 case HB_SCRIPT_ORIYA:
 case HB_SCRIPT_REJANG:
+case HB_SCRIPT_SHARADA:
 case HB_SCRIPT_SINHALA:
 case HB_SCRIPT_SUNDANESE:
 case HB_SCRIPT_TAI_THAM:
+case HB_SCRIPT_TAKRI:
 case HB_SCRIPT_TAMIL:
 case HB_SCRIPT_TELUGU:
   return hb_ot_complex_shaper_indic;
commit f32c0012ad794cd2df669dfc7b0438fafbe38b2d
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Mar 7 12:53:34 2012 -0500

Add Unicode 6.1.0 scripts

diff --git a/src/hb-common.h b/src/hb-common.h
index 75ae899..ca51c1f 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -285,6 +285,15 @@ typedef enum
   HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'),
   HB_SCRIPT_MANDAIC= HB_TAG ('M','a','n','d'),
 
+  /* Unicode-6.1 additions */
+  HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'),
+  HB_SCRIPT_MEROITIC_CURSIVE   = HB_TAG ('M','e','r','c'),
+  HB_SCRIPT_MEROITIC_HIEROGLYPHS   = HB_TAG ('M','e','r','o'),
+  HB_SCRIPT_MIAO   = HB_TAG ('P','l','r','d'),
+  HB_SCRIPT_SHARADA= HB_TAG ('S','h','r','d'),
+  HB_SCRIPT_SORA_SOMPENG   = HB_TAG ('S','o','r','a'),
+  HB_SCRIPT_TAKRI  = HB_TAG ('T','a','k','r'),
+
   /* No script set */
   HB_SCRIPT_INVALID= HB_TAG_NONE
 } hb_script_t;
diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index f990988..26d40a3 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -144,7 +144,16 @@ glib_script_to_script[] =
   /* Unicode-6.0 additions */
   HB_SCRIPT_BATAK,
   HB_SCRIPT_BRAHMI,
-  HB_SCRIPT_MANDAIC
+  HB_SCRIPT_MANDAIC,
+
+  /* Unicode-6.1 additions */
+  HB_SCRIPT_CHAKMA,
+  HB_SCRIPT_MEROITIC_CURSIVE,
+  HB_SCRIPT_MEROITIC_HIEROGLYPHS,
+  HB_SCRIPT_MIAO,
+  HB_SCRIPT_SHARADA,
+  HB_SCRIPT_SORA_SOMPENG,
+  HB_SCRIPT_TAKRI
 };
 #endif
 
commit 50e810cd0e55c25fddb0a2fd0861c51fbf65700e
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Mar 7 12:49:08 2012 -0500

Lydian and Kharoshthi are right-to-left

diff --git a/src/hb-common.cc b/src/hb-common.cc
index 6093289..170b75f 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -274,10 +274,16 @@ hb_script_get_horizontal_direction (hb_script_t script)
 /* Unicode-4.0 additions */
 case HB_SCRIPT_CYPRIOT:
 
+/* Unicode-4.1 additions */
+case HB_SCRIPT_KHAROSHTHI:
+
 /* Unicode-5.0 additions */
 case HB_SCRIPT_PHOENICIAN:
 case HB_SCRIPT_NKO:
 
+/* Unicode-5.1 additions */
+case HB_SCRIPT_LYDIAN:
+
 /* Unicode-5.2 additions */
 case HB_SCRIPT_AVESTAN:
 case HB_SCRIPT_IMPERIAL_ARAMAIC:
commit a52835635e4a2a12715aff2febb561515a10cd5a
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Mar 7 12:38:39 2012 -0500

Whitespace

diff --git a/src/hb-common.h b/src/hb-common.h
index b7fef32..75ae899 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -176,117 +176,117 @@ typedef enum
 /* http://unicode.org/iso15924/ */
 typedef enum
 {
-  HB_SCRIPT_COMMON  = HB_TAG ('Z','y','y','y'),
-  HB_SCRIPT_INHERITED   = HB_TAG ('Z','i','n','h'),
-  HB_SCRIPT_ARABIC  = HB_TAG ('A','r','a','b'),
-  HB_SCRIPT_ARMENIAN= HB_TAG ('A','r','m','n'),
-  HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
-  HB_SCRIPT_BOPOMOFO= HB_TAG 

Re: [HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2012-03-07 Thread Behdad Esfahbod
On 03/07/2012 12:56 PM, Behdad Esfahbod wrote:

 Route three Unicode 6.1 scripts through Indic shaper

Martin, Jonathan, can you comment on these?  Do they need any complex shaping
at all?

Thanks,
behdad


 
 diff --git a/src/hb-ot-shape-complex-private.hh 
 b/src/hb-ot-shape-complex-private.hh
 index 652d90a..52d0523 100644
 --- a/src/hb-ot-shape-complex-private.hh
 +++ b/src/hb-ot-shape-complex-private.hh
 @@ -79,7 +79,9 @@ hb_ot_shape_complex_categorize (const 
 hb_segment_properties_t *props)
  /* Note:
   *
   * These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, 
 but according
 - * to Martin Hosken do not require complex shaping.
 + * to Martin Hosken and Jonathan Kew do not require complex shaping.
 + *
 + * TODO We should automate figuring out which scripts do not need 
 complex shaping
   *
   * TODO We currently keep data for these scripts in our indic table.  
 Need to fix the
   * generator to not do that.
 @@ -113,6 +115,7 @@ hb_ot_shape_complex_categorize (const 
 hb_segment_properties_t *props)
  case HB_SCRIPT_BALINESE:
  case HB_SCRIPT_BENGALI:
  case HB_SCRIPT_BUGINESE:
 +case HB_SCRIPT_CHAKMA:
  case HB_SCRIPT_CHAM:
  case HB_SCRIPT_DEVANAGARI:
  case HB_SCRIPT_GUJARATI:
 @@ -127,9 +130,11 @@ hb_ot_shape_complex_categorize (const 
 hb_segment_properties_t *props)
  case HB_SCRIPT_NEW_TAI_LUE:
  case HB_SCRIPT_ORIYA:
  case HB_SCRIPT_REJANG:
 +case HB_SCRIPT_SHARADA:
  case HB_SCRIPT_SINHALA:
  case HB_SCRIPT_SUNDANESE:
  case HB_SCRIPT_TAI_THAM:
 +case HB_SCRIPT_TAKRI:
  case HB_SCRIPT_TAMIL:
  case HB_SCRIPT_TELUGU:
return hb_ot_complex_shaper_indic;
 commit f32c0012ad794cd2df669dfc7b0438fafbe38b2d
 Author: Behdad Esfahbod beh...@behdad.org
 Date:   Wed Mar 7 12:53:34 2012 -0500
 
 Add Unicode 6.1.0 scripts
 
 diff --git a/src/hb-common.h b/src/hb-common.h
 index 75ae899..ca51c1f 100644
 --- a/src/hb-common.h
 +++ b/src/hb-common.h
 @@ -285,6 +285,15 @@ typedef enum
HB_SCRIPT_BRAHMI   = HB_TAG ('B','r','a','h'),
HB_SCRIPT_MANDAIC  = HB_TAG ('M','a','n','d'),
  
 +  /* Unicode-6.1 additions */
 +  HB_SCRIPT_CHAKMA   = HB_TAG ('C','a','k','m'),
 +  HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'),
 +  HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'),
 +  HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'),
 +  HB_SCRIPT_SHARADA  = HB_TAG ('S','h','r','d'),
 +  HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'),
 +  HB_SCRIPT_TAKRI= HB_TAG ('T','a','k','r'),
 +
/* No script set */
HB_SCRIPT_INVALID  = HB_TAG_NONE
  } hb_script_t;
 diff --git a/src/hb-glib.cc b/src/hb-glib.cc
 index f990988..26d40a3 100644
 --- a/src/hb-glib.cc
 +++ b/src/hb-glib.cc
 @@ -144,7 +144,16 @@ glib_script_to_script[] =
/* Unicode-6.0 additions */
HB_SCRIPT_BATAK,
HB_SCRIPT_BRAHMI,
 -  HB_SCRIPT_MANDAIC
 +  HB_SCRIPT_MANDAIC,
 +
 +  /* Unicode-6.1 additions */
 +  HB_SCRIPT_CHAKMA,
 +  HB_SCRIPT_MEROITIC_CURSIVE,
 +  HB_SCRIPT_MEROITIC_HIEROGLYPHS,
 +  HB_SCRIPT_MIAO,
 +  HB_SCRIPT_SHARADA,
 +  HB_SCRIPT_SORA_SOMPENG,
 +  HB_SCRIPT_TAKRI
  };
  #endif
  
 commit 50e810cd0e55c25fddb0a2fd0861c51fbf65700e
 Author: Behdad Esfahbod beh...@behdad.org
 Date:   Wed Mar 7 12:49:08 2012 -0500
 
 Lydian and Kharoshthi are right-to-left
 
 diff --git a/src/hb-common.cc b/src/hb-common.cc
 index 6093289..170b75f 100644
 --- a/src/hb-common.cc
 +++ b/src/hb-common.cc
 @@ -274,10 +274,16 @@ hb_script_get_horizontal_direction (hb_script_t script)
  /* Unicode-4.0 additions */
  case HB_SCRIPT_CYPRIOT:
  
 +/* Unicode-4.1 additions */
 +case HB_SCRIPT_KHAROSHTHI:
 +
  /* Unicode-5.0 additions */
  case HB_SCRIPT_PHOENICIAN:
  case HB_SCRIPT_NKO:
  
 +/* Unicode-5.1 additions */
 +case HB_SCRIPT_LYDIAN:
 +
  /* Unicode-5.2 additions */
  case HB_SCRIPT_AVESTAN:
  case HB_SCRIPT_IMPERIAL_ARAMAIC:
 commit a52835635e4a2a12715aff2febb561515a10cd5a
 Author: Behdad Esfahbod beh...@behdad.org
 Date:   Wed Mar 7 12:38:39 2012 -0500
 
 Whitespace
 
 diff --git a/src/hb-common.h b/src/hb-common.h
 index b7fef32..75ae899 100644
 --- a/src/hb-common.h
 +++ b/src/hb-common.h
 @@ -176,117 +176,117 @@ typedef enum
  /* http://unicode.org/iso15924/ */
  typedef enum
  {
 -  HB_SCRIPT_COMMON  = HB_TAG ('Z','y','y','y'),
 -  HB_SCRIPT_INHERITED   = HB_TAG ('Z','i','n','h'),
 -  HB_SCRIPT_ARABIC  = HB_TAG ('A','r','a','b'),
 -  HB_SCRIPT_ARMENIAN= HB_TAG ('A','r','m','n'),
 -  HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
 -  HB_SCRIPT_BOPOMOFO= HB_TAG ('B','o','p','o'),
 -  HB_SCRIPT_CHEROKEE= HB_TAG ('C','h','e','r'),
 -  HB_SCRIPT_COPTIC  = HB_TAG 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2011-08-09 Thread Behdad Esfahbod
 Makefile.am   |3 
 configure.ac  |1 
 src/Makefile.am   |   13 -
 src/hb-uniscribe-shape.cc |7 
 src/hb-view.cc|  568 --
 src/test.cc   |3 
 test/hb-test.h|3 
 test/test-shape-complex.c |   20 +
 util/Makefile.am  |   24 +
 util/hb-view.cc   |  568 ++
 10 files changed, 618 insertions(+), 592 deletions(-)

New commits:
commit 511a136f0c092880b19250a5df53bcf9f4b043ca
Author: Behdad Esfahbod beh...@behdad.org
Date:   Tue Aug 9 15:03:00 2011 +0200

Move hb-view into util/

diff --git a/Makefile.am b/Makefile.am
index bb68ede..8b69c2d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@
 
 NULL =
 
-SUBDIRS = src test
+SUBDIRS = src util test
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
@@ -76,5 +76,4 @@ $(gpg_file): $(sha256_file)
 release-files: $(tar_file) $(sha256_file) $(gpg_file)
 
 
-
 -include $(top_srcdir)/git.mk
diff --git a/configure.ac b/configure.ac
index 3f13c43..d960856 100644
--- a/configure.ac
+++ b/configure.ac
@@ -161,6 +161,7 @@ Makefile
 harfbuzz.pc
 src/Makefile
 src/hb-version.h
+util/Makefile
 test/Makefile
 ])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b0307a..62a5b39 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -149,19 +149,6 @@ hb-ot-shape-complex-indic-machine.hh: 
hb-ot-shape-complex-indic-machine.rl
 noinst_PROGRAMS = main test
 bin_PROGRAMS =
 
-if HAVE_GLIB
-if HAVE_FREETYPE
-if HAVE_CAIRO_FT
-if HAVE_CAIRO_PNG
-hb_view_SOURCES = hb-view.cc
-hb_view_CPPFLAGS = $(HBCFLAGS) $(CAIRO_FT_CFLAGS) $(CAIRO_PNG_CFLAGS)
-hb_view_LDADD = libharfbuzz.la -lm $(HBLIBS) $(CAIRO_FT_LIBS) $(CAIRO_PNG_LIBS)
-bin_PROGRAMS += hb-view
-endif
-endif
-endif
-endif
-
 main_SOURCES = main.cc
 main_CPPFLAGS = $(HBCFLAGS)
 main_LDADD = libharfbuzz.la $(HBLIBS)
diff --git a/src/hb-view.cc b/src/hb-view.cc
deleted file mode 100644
index dc3fc47..000
--- a/src/hb-view.cc
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * Copyright © 2010  Behdad Esfahbod
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN AS IS BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifdef HAVE_CONFIG_H
-#include config.h
-#endif
-
-#include unistd.h
-#include getopt.h
-#include stdlib.h
-#include stdio.h
-#include string.h
-#include math.h
-#include locale.h
-
-#include glib.h
-
-#include cairo-ft.h
-#include hb-ft.h
-
-
-
-/* Controlled by cmd-line options */
-static int margin_t = 10;
-static int margin_b = 10;
-static int margin_l = 10;
-static int margin_r = 10;
-static int line_space = 0;
-static int face_index = 0;
-static double font_size = 18;
-static const char *fore = #00;
-static const char *back = #ff;
-static const char *text = NULL;
-static const char *font_file = NULL;
-static const char *out_file = /dev/stdout;
-static const char *direction = NULL;
-static const char *script = NULL;
-static const char *language = NULL;
-static hb_feature_t *features = NULL;
-static unsigned int num_features;
-static hb_bool_t annotate = FALSE;
-static hb_bool_t debug = FALSE;
-
-/* Ugh, global vars.  Ugly, but does the job */
-static int width = 0;
-static int height = 0;
-static cairo_surface_t *surface = NULL;
-static cairo_pattern_t *fore_pattern = NULL;
-static cairo_pattern_t *back_pattern = NULL;
-static cairo_font_face_t *cairo_face;
-
-
-G_GNUC_NORETURN static void
-usage (FILE *f, int status)
-{
-  fprintf (f, usage: hb-view [OPTS...] font-file text\n);
-  exit (status);
-}
-
-G_GNUC_NORETURN static void
-version (void)
-{
-  printf (hb-view (harfbuzz) %s\n, HB_VERSION_STRING);
-  exit (0);
-}
-
-static void parse_features (char *s);
-
-static void
-parse_opts (int argc, char **argv)
-{
-  argv[0] = (char *) hb-view;
-  while (1)
-{
-  int option_index = 0, c;
-  static const struct option long_options[] = {
-   {annotate, 0, annotate, TRUE},
-   

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2011-08-05 Thread Behdad Esfahbod
 src/check-header-guards.sh  |1 
 src/hb-common.cc|8 +++---
 src/hb-open-type-private.hh |   10 +++
 src/hb-shape.cc |   58 +---
 src/hb-shape.h  |3 ++
 src/hb-view.cc  |2 -
 test/Makefile.am|2 +
 test/test-c.c   |8 ++
 test/test-shape.c   |   15 +++
 9 files changed, 83 insertions(+), 24 deletions(-)

New commits:
commit 9da554504e30a326fc57b28cdb0e57108bfa9555
Author: Behdad Esfahbod beh...@behdad.org
Date:   Fri Aug 5 19:48:49 2011 -0400

Add hb_shape_list_shapers()

diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index 9e4469d..78c39dd 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -66,8 +66,16 @@ static struct static_shaper_list_t
   {
 char *env = getenv (HB_SHAPER_LIST);
 shaper_list = NULL;
-if (!env || !*env)
+if (!env || !*env) {
+fallback:
+  ASSERT_STATIC ((ARRAY_LENGTH (shapers) + 1) * sizeof (*shaper_list) = 
sizeof (static_buffer));
+  shaper_list = (const char **) static_buffer;
+  unsigned int i;
+  for (i = 0; i  ARRAY_LENGTH (shapers); i++)
+shaper_list[i] = shapers[i].name;
+  shaper_list[i] = NULL;
   return;
+}
 
 unsigned int count = 3; /* initial, fallback, null */
 for (const char *p = env; (p == strchr (p, ','))  p++; )
@@ -76,7 +84,7 @@ static struct static_shaper_list_t
 unsigned int len = strlen (env);
 
 if (count  100 || len  1000)
-  return;
+  goto fallback;
 
 len += count * sizeof (*shaper_list) + 1;
 char *buffer = len  sizeof (static_buffer) ? static_buffer : (char *) 
malloc (len);
@@ -100,7 +108,13 @@ static struct static_shaper_list_t
 
   const char **shaper_list;
   char static_buffer[32];
-} env_shaper_list;
+} static_shaper_list;
+
+const char **
+hb_shape_list_shapers (void)
+{
+  return static_shaper_list.shaper_list;
+}
 
 hb_bool_t
 hb_shape_full (hb_font_t   *font,
@@ -111,7 +125,7 @@ hb_shape_full (hb_font_t   *font,
   const char **shaper_list)
 {
   if (likely (!shaper_list))
-shaper_list = env_shaper_list.shaper_list;
+shaper_list = static_shaper_list.shaper_list;
 
   if (likely (!shaper_list)) {
 for (unsigned int i = 0; i  ARRAY_LENGTH (shapers); i++)
diff --git a/src/hb-shape.h b/src/hb-shape.h
index 75818dc..18b35ae 100644
--- a/src/hb-shape.h
+++ b/src/hb-shape.h
@@ -56,6 +56,9 @@ hb_shape_full (hb_font_t   *font,
   const char  *shaper_options,
   const char **shaper_list);
 
+const char **
+hb_shape_list_shapers (void);
+
 
 HB_END_DECLS
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 0fbc689..18f36df 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -25,9 +25,11 @@ TEST_PROGS = \
test-version \
$(NULL)
 
+if HAVE_OT
 TEST_PROGS += \
test-ot-tag \
$(NULL)
+endif
 
 # Tests for header compilation
 TEST_PROGS += \
diff --git a/test/test-c.c b/test/test-c.c
index 543fa7b..e72db27 100644
--- a/test/test-c.c
+++ b/test/test-c.c
@@ -43,6 +43,14 @@
 #include hb-ft.h
 #endif
 
+#if HAVE_OT
+#include hb-ot.h
+#endif
+
+#if HAVE_UNISCRIBE
+#include hb-uniscribe.h
+#endif
+
 int
 main (int argc, char **argv)
 {
diff --git a/test/test-shape.c b/test/test-shape.c
index 5a41f0c..6d30824 100644
--- a/test/test-shape.c
+++ b/test/test-shape.c
@@ -138,6 +138,18 @@ test_shape (void)
   hb_font_destroy (font);
 }
 
+static void
+test_shape_list (void)
+{
+  const char **shapers = hb_shape_list_shapers ();
+
+  unsigned int i;
+  for (i = 0; shapers[i]; i++)
+;
+
+  g_assert_cmpint (i, , 1);
+  g_assert (!strcmp (shapers[i - 1], fallback));
+}
 
 int
 main (int argc, char **argv)
@@ -145,6 +157,9 @@ main (int argc, char **argv)
   hb_test_init (argc, argv);
 
   hb_test_add (test_shape);
+  /* TODO test fallback shaper */
+  /* TODO test shaper_full */
+  hb_test_add (test_shape_list);
 
   return hb_test_run();
 }
commit d7bf473ef222ab420456ff155ffaa09bacb3a394
Author: Behdad Esfahbod beh...@behdad.org
Date:   Fri Aug 5 18:18:21 2011 -0400

Minor

diff --git a/src/check-header-guards.sh b/src/check-header-guards.sh
index 212b803..dc1893c 100755
--- a/src/check-header-guards.sh
+++ b/src/check-header-guards.sh
@@ -10,7 +10,6 @@ test x$HBHEADERS = x  HBHEADERS=`find . -maxdepth 1 -name 
'hb*.h'`
 test x$HBSOURCES = x  HBSOURCES=`find . -maxdepth 1 -name 'hb-*.cc' -or 
-name 'hb-*.hh'`
 
 
-echo  $srcdir
 for x in $HBHEADERS $HBSOURCES; do
test -f $srcdir/$x  x=$srcdir/$x
echo $x | grep '[^h]$' -q  continue;
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index a6f1389..ae44ed7 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -338,12 +338,12 @@ struct Sanitizer
  */
 
 
-template typename Type, int Bytes class BEInt;
+template typename Type, int Bytes struct BEInt;
 
 /* LONGTERMTODO: On machines 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2011-07-20 Thread Behdad Esfahbod
 src/hb-glib.cc  |  149 +++-
 src/hb-icu.cc   |  145 ++
 src/hb-unicode.cc   |6 +-
 test/test-unicode.c |   67 +++
 4 files changed, 317 insertions(+), 50 deletions(-)

New commits:
commit 498e1a9be673bb02c00aac3f12bb4c6993a85910
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Jul 20 23:19:49 2011 -0400

[icu] Implement compose()/decompose()

diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index 4aa56f6..384b77d 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -35,6 +35,8 @@
 
 #include unicode/uversion.h
 #include unicode/uchar.h
+#include unicode/unorm.h
+#include unicode/unistr.h
 
 HB_BEGIN_DECLS
 
@@ -170,7 +172,34 @@ hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs 
HB_UNUSED,
hb_codepoint_t *ab,
void   *user_data HB_UNUSED)
 {
-  return FALSE;
+  if (!a || !b)
+return FALSE;
+
+  UChar utf16[4], normalized[5];
+  gint len;
+  hb_bool_t ret, err;
+  UErrorCode icu_err;
+
+  len = 0;
+  err = FALSE;
+  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err);
+  if (err) return FALSE;
+  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err);
+  if (err) return FALSE;
+
+  icu_err = U_ZERO_ERROR;
+  len = unorm_normalize (utf16, len, UNORM_NFC, 0, normalized, ARRAY_LENGTH 
(normalized), icu_err);
+  if (icu_err)
+return FALSE;
+  normalized[len] = 0;
+  if (u_strlen (normalized) == 1) {
+U16_GET_UNSAFE (normalized, 0, *ab);
+ret = TRUE;
+  } else {
+ret = FALSE;
+  }
+
+  return ret;
 }
 
 static hb_bool_t
@@ -180,7 +209,61 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs 
HB_UNUSED,
  hb_codepoint_t *b,
  void   *user_data HB_UNUSED)
 {
-  return FALSE;
+  UChar utf16[2], normalized[20];
+  gint len;
+  hb_bool_t ret, err;
+  UErrorCode icu_err;
+
+  len = 0;
+  err = FALSE;
+  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err);
+  if (err) return FALSE;
+
+  icu_err = U_ZERO_ERROR;
+  len = unorm_normalize (utf16, len, UNORM_NFD, 0, normalized, ARRAY_LENGTH 
(normalized), icu_err);
+  if (icu_err)
+return FALSE;
+
+  normalized[len] = 0;
+  len = u_strlen (normalized);
+
+  if (len == 1) {
+U16_GET_UNSAFE (normalized, 0, *a);
+*b = 0;
+ret = *a != ab;
+  } else if (len == 2) {
+/* Here's the ugly part: if ab decomposes to a single character and
+ * that character decomposes again, we have to detect that and undo
+ * the second part :-(. */
+UChar recomposed[20];
+icu_err = U_ZERO_ERROR;
+len = unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, 
ARRAY_LENGTH (recomposed), icu_err);
+if (icu_err)
+  return FALSE;
+U16_GET_UNSAFE (recomposed, 0, *a);
+if (*a != ab) {
+  *b = 0;
+} else {
+  len =0;
+  U16_NEXT_UNSAFE (normalized, len, *a);
+  U16_GET_UNSAFE (normalized, len, *b);
+}
+ret = TRUE;
+  } else {
+/* If decomposed to more than two characters, take the last one,
+ * and recompose the rest to get the first component. */
+U16_PREV_UNSAFE (normalized, len, *b);
+UChar recomposed[20];
+icu_err = U_ZERO_ERROR;
+len = unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, 
ARRAY_LENGTH (recomposed), icu_err);
+if (icu_err)
+  return FALSE;
+/* We expect that recomposed has exactly one character now. */
+U16_GET_UNSAFE (recomposed, 0, *a);
+ret = TRUE;
+  }
+
+  return ret;
 }
 
 extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_icu;
diff --git a/test/test-unicode.c b/test/test-unicode.c
index 09dde54..dd57984 100644
--- a/test/test-unicode.c
+++ b/test/test-unicode.c
@@ -864,6 +864,7 @@ main (int argc, char **argv)
 #endif
 #ifdef HAVE_ICU
   hb_test_add_data_flavor (hb_icu_get_unicode_funcs (),  icu,
 test_unicode_properties);
+  hb_test_add_data_flavor (hb_icu_get_unicode_funcs (),  icu,
 test_unicode_normalization);
   hb_test_add_data_flavor ((gconstpointer) script_roundtrip_icu, icu,
 test_unicode_script_roundtrip);
 #endif
 
commit ffd4a436f7baccb68a0c3602f94ea0246e32844f
Author: Behdad Esfahbod beh...@behdad.org
Date:   Wed Jul 20 22:30:29 2011 -0400

Add tests for compose()/decompose()

Adjust glib fallback implementation.

The tests are not hooked up for ICU yet.

diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index 6174498..fbf8cf5 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -244,6 +244,9 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs 
HB_UNUSED,
   /* We don't ifdef-out the fallback code such that compiler always
* sees it and makes sure it's compilable. */
 
+  if (!a || !b)
+return FALSE;
+
   gchar utf8[12];
   gchar *normalized;
   gint len;
@@ -293,8 +296,18 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs 
HB_UNUSED,
 *b = 0;
 ret = *a != ab;
   } else 

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2011-05-11 Thread Behdad Esfahbod
 src/hb-font.cc   |   10 -
 src/hb-font.h|2 
 src/hb-ft.cc |2 
 test/test-font.c |  290 ---
 4 files changed, 284 insertions(+), 20 deletions(-)

New commits:
commit 52df150efeff4cf003cee65f8c91618f1a980bc8
Author: Behdad Esfahbod beh...@behdad.org
Date:   Thu May 12 00:46:57 2011 -0400

Fix font subclass chainup

Test passing now.

diff --git a/src/hb-font.cc b/src/hb-font.cc
index 7cdf5f6..10f686e 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -536,11 +536,7 @@ hb_font_create_sub_font (hb_font_t *parent)
   font-x_ppem = parent-x_ppem;
   font-y_ppem = parent-y_ppem;
 
-  /* We can safely copy user_data from parent since we hold a reference
-   * onto it and it's immutable.  We should not copy the destroy notifiers
-   * though. */
-  font-klass = hb_font_funcs_reference (parent-klass);
-  font-user_data = parent-user_data;
+  font-klass = _hb_font_funcs_nil;
 
   return font;
 }
commit f2c1dd4f746c36a44cf33d0257a3cd800107c286
Author: Behdad Esfahbod beh...@behdad.org
Date:   Thu May 12 00:35:12 2011 -0400

[test/font] Test font_funcs subclassing

diff --git a/test/test-font.c b/test/test-font.c
index 01d20b4..aa78a20 100644
--- a/test/test-font.c
+++ b/test/test-font.c
@@ -183,7 +183,7 @@ test_fontfuncs_empty (void)
 }
 
 static void
-test_fontfuncs_custom (void)
+test_fontfuncs_nil (void)
 {
   hb_font_funcs_t *ffuncs;
 
@@ -195,6 +195,158 @@ test_fontfuncs_custom (void)
   hb_font_funcs_destroy (ffuncs);
 }
 
+static hb_bool_t
+contour_point_func1 (hb_font_t *font, void *font_data,
+hb_codepoint_t glyph, unsigned int point_index,
+hb_position_t *x, hb_position_t *y,
+void *user_data)
+{
+  if (glyph == 1) {
+*x = 2;
+*y = 3;
+return TRUE;
+  }
+  if (glyph == 2) {
+*x = 4;
+*y = 5;
+return TRUE;
+  }
+
+  return FALSE;
+}
+
+static hb_bool_t
+contour_point_func2 (hb_font_t *font, void *font_data,
+hb_codepoint_t glyph, unsigned int point_index,
+hb_position_t *x, hb_position_t *y,
+void *user_data)
+{
+  if (glyph == 1) {
+*x = 6;
+*y = 7;
+return TRUE;
+  }
+
+  return hb_font_get_contour_point (hb_font_get_parent (font),
+   glyph, point_index, x, y);
+}
+
+static void
+glyph_advance_func1 (hb_font_t *font, void *font_data,
+hb_codepoint_t glyph,
+hb_position_t *x_advance, hb_position_t *y_advance,
+void *user_data)
+{
+  if (glyph == 1) {
+*x_advance = 8;
+*y_advance = 9;
+  }
+}
+
+static void
+test_fontfuncs_subclassing (void)
+{
+  hb_blob_t *blob;
+  hb_face_t *face;
+
+  hb_font_funcs_t *ffuncs1;
+  hb_font_funcs_t *ffuncs2;
+
+  hb_font_t *font1;
+  hb_font_t *font2;
+  hb_font_t *font3;
+
+  hb_position_t x;
+  hb_position_t y;
+
+  blob = hb_blob_create (test_data, sizeof (test_data), 
HB_MEMORY_MODE_READONLY, NULL, NULL);
+  face = hb_face_create (blob, 0);
+  hb_blob_destroy (blob);
+  font1 = hb_font_create (face);
+  hb_face_destroy (face);
+  hb_font_set_scale (font1, 10, 10);
+
+  /* setup font1 */
+  ffuncs1 = hb_font_funcs_create ();
+  hb_font_funcs_set_contour_point_func (ffuncs1, contour_point_func1, NULL, 
NULL);
+  hb_font_funcs_set_glyph_advance_func (ffuncs1, glyph_advance_func1, NULL, 
NULL);
+  hb_font_set_funcs (font1, ffuncs1, NULL, NULL);
+  hb_font_funcs_destroy (ffuncs1);
+
+  x = y = 1;
+  g_assert (hb_font_get_contour_point (font1, 1, 2, x, y));
+  g_assert_cmpint (x, ==, 2);
+  g_assert_cmpint (y, ==, 3);
+  g_assert (hb_font_get_contour_point (font1, 2, 5, x, y));
+  g_assert_cmpint (x, ==, 4);
+  g_assert_cmpint (y, ==, 5);
+  g_assert (!hb_font_get_contour_point (font1, 3, 7, x, y));
+  g_assert_cmpint (x, ==, 0);
+  g_assert_cmpint (y, ==, 0);
+  hb_font_get_glyph_advance (font1, 1, x, y);
+  g_assert_cmpint (x, ==, 8);
+  g_assert_cmpint (y, ==, 9);
+  hb_font_get_glyph_advance (font1, 2, x, y);
+  g_assert_cmpint (x, ==, 0);
+  g_assert_cmpint (y, ==, 0);
+
+
+  font2 = hb_font_create_sub_font (font1);
+  g_assert (hb_font_is_immutable (font1));
+  hb_font_destroy (font1);
+
+  /* setup font2 to override some funcs */
+  ffuncs2 = hb_font_funcs_create ();
+  hb_font_funcs_set_contour_point_func (ffuncs2, contour_point_func2, NULL, 
NULL);
+  hb_font_set_funcs (font2, ffuncs2, NULL, NULL);
+  hb_font_funcs_destroy (ffuncs2);
+
+  x = y = 1;
+  g_assert (hb_font_get_contour_point (font2, 1, 2, x, y));
+  g_assert_cmpint (x, ==, 6);
+  g_assert_cmpint (y, ==, 7);
+  g_assert (hb_font_get_contour_point (font2, 2, 5, x, y));
+  g_assert_cmpint (x, ==, 4);
+  g_assert_cmpint (y, ==, 5);
+  g_assert (!hb_font_get_contour_point (font2, 3, 7, x, y));
+  g_assert_cmpint (x, ==, 0);
+  g_assert_cmpint (y, ==, 0);
+  hb_font_get_glyph_advance (font2, 1, x, y);
+  g_assert_cmpint (x, ==, 8);
+  g_assert_cmpint (y, ==, 9);
+  

[HarfBuzz] harfbuzz-ng: Branch 'master' - 5 commits

2010-07-07 Thread Behdad Esfahbod
 src/Makefile.am|4 -
 src/check-header-guards.sh |   20 +
 src/check-libstdc++.sh |1 
 src/hb-buffer-private.hh   |6 -
 src/hb-font-private.hh |6 -
 src/hb-object-private.h|6 -
 src/hb-open-file-private.hh|1 
 src/hb-open-type-private.hh|   53 +
 src/hb-ot-layout-common-private.hh |  145 +
 src/hb-ot-layout-private.hh|6 -
 src/hb-ot-shape.h  |2 
 11 files changed, 138 insertions(+), 112 deletions(-)

New commits:
commit cc8a4abea68f2dba26feb5785f9e518e6853c744
Author: Behdad Esfahbod beh...@behdad.org
Date:   Thu Jul 8 00:40:04 2010 -0400

Use bsearch where applicable

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 59c7866..9cc0518 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -394,6 +394,7 @@ struct IntType
   inline operator Type(void) const { return v; }
   inline bool operator == (const IntTypeType o) const { return v == o.v; }
   inline bool operator != (const IntTypeType o) const { return v != o.v; }
+  inline int cmp (Type b) const { Type a = v; return b  a ? -1 : b == a ? 0 : 
+1; }
   inline bool sanitize (hb_sanitize_context_t *c) {
 TRACE_SANITIZE ();
 return likely (c-check_struct (this));
@@ -707,4 +708,52 @@ struct HeadlessArrayOf
 };
 
 
+/* An array with sorted elements.  Supports binary searching. */
+template typename Type
+struct SortedArrayOf : ArrayOfType {
+
+  template typename SearchType
+  inline int search (const SearchType x) const {
+class Cmp {
+  public: static int cmp (const void *p1, const void *p2) {
+   const SearchType *a = (const SearchType *) p1;
+   const Type *b = (const Type *) p2;
+   return b-cmp (*a);
+  }
+};
+const Type *p = (const Type *) bsearch (x, this-array, this-len, sizeof 
(this-array[0]), Cmp::cmp);
+return p ? p - this-array : -1;
+  }
+
+  inline bool sanitize_order (hb_sanitize_context_t *c) {
+/* Make sure the list is sorted, since we bsearch in it. */
+unsigned int count = this-len;
+for (unsigned int i = 1; i  count; i++)
+  if (unlikely (this-array[i].cmp (this-array[i-1])  0)) {
+   /* We need to sort the entries. */
+   if (!c-can_edit (this, this-get_size ())) return false;
+   class Cmp {
+ public: static int cmp (const void *p1, const void *p2) {
+   const Type *a = (const Type *) p1;
+   const Type *b = (const Type *) p2;
+   return b-cmp (*a);
+ }
+   };
+   qsort (this-array, this-len, sizeof (this-array[0]), Cmp::cmp);
+  }
+return true;
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c) {
+TRACE_SANITIZE ();
+return ArrayOfType::sanitize (c)  sanitize_order (c);
+  }
+
+  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+TRACE_SANITIZE ();
+return ArrayOfType::sanitize (c, base)  sanitize_order (c);
+  }
+};
+
+
 #endif /* HB_OPEN_TYPE_PRIVATE_HH */
diff --git a/src/hb-ot-layout-common-private.hh 
b/src/hb-ot-layout-common-private.hh
index f965491..5954499 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -51,6 +51,14 @@
 template typename Type
 struct Record
 {
+  inline int cmp (const Record other) const {
+return cmp (other.tag);
+  }
+  inline int cmp (hb_tag_t b) const {
+hb_tag_t a = tag;
+return b  a ? -1 : b == a ? 0 : -1;
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c, void *base) {
 TRACE_SANITIZE ();
 return c-check_struct (this)
@@ -66,7 +74,7 @@ struct Record
 };
 
 template typename Type
-struct RecordArrayOf : ArrayOfRecordType  {
+struct RecordArrayOf : SortedArrayOfRecordType  {
   inline const Tag get_tag (unsigned int i) const
   {
 if (unlikely (i = this-len)) return Null(Tag);
@@ -86,21 +94,14 @@ struct RecordArrayOf : ArrayOfRecordType  {
   }
   inline bool find_index (hb_tag_t tag, unsigned int *index) const
   {
-Tag t;
-t.set (tag);
-/* TODO: bsearch (need to sort in sanitize) */
-const RecordType *a = this-array;
-unsigned int count = this-len;
-for (unsigned int i = 0; i  count; i++)
-{
-  if (t == a[i].tag)
-  {
+int i = this-search (tag);
+if (i != -1) {
 if (index) *index = i;
 return true;
-  }
+} else {
+  if (index) *index = Index::NOT_FOUND_INDEX;
+  return false;
 }
-if (index) *index = Index::NOT_FOUND_INDEX;
-return false;
   }
 };
 
@@ -117,6 +118,31 @@ struct RecordListOf : RecordArrayOfType
 };
 
 
+struct RangeRecord
+{
+  inline int cmp (const RangeRecord other) const {
+hb_codepoint_t a = start, b = other.start;
+return b  a ? -1 : b == a ? 0 : +1;
+  }
+  inline int cmp (hb_codepoint_t g) const {
+hb_codepoint_t a = start, b = end;
+return g  a ? -1 : g = b ? 0 : +1 ;
+  }
+
+  inline bool