[HarfBuzz] harfbuzz-ng: Branch 'master' - 11 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Fri May 21 06:18:24 PDT 2010
configure.ac | 6
contrib/python/lib/harfbuzz.pyx | 308 ++++++++++++++++++++++++++++++++++++++
contrib/python/runpy | 2
contrib/python/scripts/hbtestfont | 35 ++++
contrib/python/setup.py | 24 ++
src/Makefile.am | 12 +
src/hb-common.c | 41 +++++
src/hb-common.h | 3
src/hb-font.cc | 2
src/hb-font.h | 1
src/hb-graphite.cc | 304 +++++++++++++++++++++++++++++++++++++
src/hb-graphite.h | 46 +++++
src/hb-icu.c | 29 +++
src/hb-open-type-private.hh | 3
src/hb-ot-shape.cc | 41 +++--
src/hb-ot-tag.c | 33 +++-
src/hb-ot-tag.h | 3
src/hb-shape.cc | 15 +
src/hb-unicode.c | 19 ++
src/hb-unicode.h | 19 ++
20 files changed, 931 insertions(+), 15 deletions(-)
New commits:
commit dd47924d88d86b83e7f3ab040de6e7136ac0ca09
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 14:18:08 2010 +0100
Fix warnings
diff --git a/src/hb-graphite.cc b/src/hb-graphite.cc
index ba1169a..f1af2c3 100644
--- a/src/hb-graphite.cc
+++ b/src/hb-graphite.cc
@@ -51,7 +51,6 @@ class GrBufferTextSrc : public gr::ITextSource
public:
GrBufferTextSrc(hb_buffer_t *buff, hb_feature_t *feats, unsigned int num_features)
{
- int i;
hb_feature_t *aFeat = feats;
featureSetting *aNewFeat;
@@ -59,7 +58,7 @@ public:
features = new featureSetting[num_features];
nFeatures = num_features;
aNewFeat = features;
- for (i = 0; i < num_features; i++, aFeat++, aNewFeat++)
+ for (unsigned int i = 0; i < num_features; i++, aFeat++, aNewFeat++)
{
aNewFeat->id = aFeat->tag;
aNewFeat->value = aFeat->value;
@@ -70,12 +69,10 @@ public:
virtual size_t getLength() { return buffer->len; };
virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer)
{
- int i;
-
assert(cch <= buffer->len);
if (cch > buffer->len)
return 0;
- for (i = ichMin; i < ichMin + cch; i++)
+ for (unsigned int i = ichMin; i < ichMin + cch; i++)
prgchBuffer[i - ichMin] = buffer->info[i].codepoint;
return (cch - ichMin);
};
@@ -107,9 +104,8 @@ public:
{ return std::pair<gr::toffset, gr::toffset>(0, buffer->len); };
virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset)
{
- int i;
featureSetting *aFeat = features;
- for (i = 0; i < nFeatures; i++, aFeat++, prgfset++)
+ for (unsigned int i = 0; i < nFeatures; i++, aFeat++, prgfset++)
{
prgfset->id = aFeat->id;
prgfset->value = aFeat->value;
@@ -268,7 +264,7 @@ hb_graphite_shape (hb_font_t *font,
hb_buffer_ensure(buffer, numGlyphs);
pSegment.getUniscribeClusters(firsts, numChars, NULL, flags, numGlyphs, NULL);
glyph_range = pSegment.glyphs();
- for (pGlyph = glyph_infos, iGlyph = glyph_range.first; iGlyph != glyph_range.second;
+ for (pGlyph = glyph_infos, iGlyph = glyph_range.first; iGlyph < glyph_range.second;
iGlyph++, pGlyph++)
{ *pGlyph = iGlyph->glyphID(); }
@@ -289,7 +285,7 @@ hb_graphite_shape (hb_font_t *font,
float curradvx = 0., curradvy = 0.;
for (pPosition = hb_buffer_get_glyph_positions(buffer), iGlyph = glyph_range.first;
- iGlyph != glyph_range.second; pPosition++, iGlyph++)
+ iGlyph < glyph_range.second; pPosition++, iGlyph++)
{
pPosition->x_offset = iGlyph->origin() - curradvx;
pPosition->y_offset = iGlyph->yOffset() - curradvy;
commit 305ba8671553cd955c20a54db622666c0bb02532
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 14:02:20 2010 +0100
Import Graphite shaping backend by Martin Hosken
diff --git a/configure.ac b/configure.ac
index 0cc01b7..721c912 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,6 +33,12 @@ if $have_icu; then
fi
AM_CONDITIONAL(HAVE_ICU, $have_icu)
+PKG_CHECK_MODULES(GRAPHITE, silgraphite, have_graphite=true, have_graphite=false)
+if $have_graphite; then
+ AC_DEFINE(HAVE_GRAPHITE, 1, [Have Graphite library])
+fi
+AM_CONDITIONAL(HAVE_GRAPHITE, $have_graphite)
+
PKG_CHECK_MODULES(FREETYPE, freetype2, have_freetype=true, have_freetype=false)
if $have_freetype; then
AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library])
diff --git a/src/Makefile.am b/src/Makefile.am
index 70cbfd8..0ed02e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,17 @@ HBHEADERS += \
$(NULL)
endif
+if HAVE_GRAPHITE
+HBCFLAGS += $(GRAPHITE_CFLAGS)
+HBLIBS += $(GRAPHITE_LIBS)
+HBSOURCES += \
+ hb-graphite.cc \
+ $(NULL)
+HBHEADERS += \
+ hb-graphite.h \
+ $(NULL)
+endif
+
CXXLINK = $(LINK)
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
diff --git a/src/hb-graphite.cc b/src/hb-graphite.cc
new file mode 100644
index 0000000..ba1169a
--- /dev/null
+++ b/src/hb-graphite.cc
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2009, Martin Hosken
+ * Copyright (C) 2009, SIL International
+ *
+ * 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.
+ */
+
+#include <graphite/GrClient.h>
+#include <graphite/ITextSource.h>
+#include <graphite/GrData.h>
+#include <graphite/GrConstants.h>
+#include <graphite/Segment.h>
+#include "hb-buffer-private.hh"
+#include "hb-font-private.hh"
+#include "hb-graphite.h"
+#include <map>
+
+namespace TtfUtil
+{
+extern int FontAscent(const void *pOS2);
+extern int FontDescent(const void *pOS2);
+extern int DesignUnits(const void *pHead);
+extern bool FontOs2Style(const void *pOS2, bool &fBold, bool &fItalic);
+}
+
+typedef struct _featureSetting {
+ unsigned int id;
+ int value;
+} featureSetting;
+
+class GrBufferTextSrc : public gr::ITextSource
+{
+public:
+ GrBufferTextSrc(hb_buffer_t *buff, hb_feature_t *feats, unsigned int num_features)
+ {
+ int i;
+ hb_feature_t *aFeat = feats;
+ featureSetting *aNewFeat;
+
+ buffer = hb_buffer_reference(buff);
+ features = new featureSetting[num_features];
+ nFeatures = num_features;
+ aNewFeat = features;
+ for (i = 0; i < num_features; i++, aFeat++, aNewFeat++)
+ {
+ aNewFeat->id = aFeat->tag;
+ aNewFeat->value = aFeat->value;
+ }
+ };
+ ~GrBufferTextSrc() { hb_buffer_destroy(buffer); delete[] features; };
+ virtual gr::UtfType utfEncodingForm() { return gr::kutf32; };
+ virtual size_t getLength() { return buffer->len; };
+ virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer)
+ {
+ int i;
+
+ assert(cch <= buffer->len);
+ if (cch > buffer->len)
+ return 0;
+ for (i = ichMin; i < ichMin + cch; i++)
+ prgchBuffer[i - ichMin] = buffer->info[i].codepoint;
+ return (cch - ichMin);
+ };
+ virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf16 * prgchBuffer) { return 0 ;};
+ virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf8 * prgchBuffer) { return 0; };
+ virtual bool getRightToLeft(gr::toffset ich)
+ { return hb_buffer_get_direction(buffer) == HB_DIRECTION_RTL; };
+ virtual unsigned int getDirectionDepth(gr::toffset ich)
+ { return hb_buffer_get_direction(buffer) == HB_DIRECTION_RTL ? 1 : 0; };
+ virtual float getVerticalOffset(gr::toffset ich) { return 0; };
+ virtual gr::isocode getLanguage(gr::toffset ich)
+ {
+ gr::isocode aLang;
+ char *p = (char *)(buffer->language);
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ if (p != NULL)
+ aLang.rgch[i] = *p;
+ else
+ aLang.rgch[i] = 0;
+ if (p && *p)
+ p++;
+ }
+ return aLang;
+ }
+
+ virtual std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich)
+ { return std::pair<gr::toffset, gr::toffset>(0, buffer->len); };
+ virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset)
+ {
+ int i;
+ featureSetting *aFeat = features;
+ for (i = 0; i < nFeatures; i++, aFeat++, prgfset++)
+ {
+ prgfset->id = aFeat->id;
+ prgfset->value = aFeat->value;
+ }
+ return nFeatures;
+ }
+ virtual bool sameSegment(gr::toffset ich1, gr::toffset ich2) {return true; };
+
+private:
+ hb_buffer_t *buffer;
+ featureSetting *features;
+ unsigned int nFeatures;
+};
+
+class GrHbFont : public gr::Font
+{
+public:
+ GrHbFont(hb_font_t *font, hb_face_t *face) : gr::Font()
+ { m_font = hb_font_reference(font); m_face = hb_face_reference(face); initfont(); };
+ ~GrHbFont()
+ {
+ std::map<hb_tag_t,hb_blob_t *>::iterator p = m_blobs.begin();
+ while (p != m_blobs.end())
+ { hb_blob_destroy((p++)->second); }
+ hb_font_destroy(m_font);
+ hb_face_destroy(m_face);
+ };
+ GrHbFont (const GrHbFont &font) : gr::Font(font)
+ {
+ *this = font;
+ m_blobs = std::map<hb_tag_t, hb_blob_t *>(font.m_blobs);
+ std::map<hb_tag_t,hb_blob_t *>::iterator p=m_blobs.begin();
+ while (p != m_blobs.end()) { hb_blob_reference((*p++).second); }
+ hb_font_reference(m_font);
+ hb_face_reference(m_face);
+ };
+ virtual GrHbFont *copyThis() { return new GrHbFont(*this); };
+ virtual bool bold() { return m_bold; };
+ virtual bool italic() { return m_italic; };
+ virtual float ascent() { float asc; getFontMetrics(&asc, NULL, NULL); return asc; };
+ virtual float descent() { float desc; getFontMetrics(NULL, &desc, NULL); return desc; };
+ virtual float height()
+ { float asc, desc; getFontMetrics(&asc, &desc, NULL); return (asc + desc); };
+ virtual unsigned int getDPIx() { return m_font->x_ppem; };
+ virtual unsigned int getDPIy() { return m_font->y_ppem; };
+ virtual const void *getTable(gr::fontTableId32 tableID, size_t *pcbsize)
+ {
+ hb_blob_t *blob;
+ std::map<hb_tag_t,hb_blob_t *>::iterator p=m_blobs.find((hb_tag_t)tableID);
+ if (p == m_blobs.end())
+ {
+ blob = hb_face_get_table(m_face, (hb_tag_t)tableID);
+ m_blobs[(hb_tag_t)tableID] = blob;
+ }
+ else
+ { blob = p->second; }
+
+ const char *res = hb_blob_lock(blob);
+ if (pcbsize)
+ *pcbsize = hb_blob_get_length(blob);
+ hb_blob_unlock(blob);
+ return (const void *)res;
+ }
+
+ virtual void getFontMetrics(float *pAscent, float *pDescent, float *pEmSquare)
+ {
+ if (pAscent) *pAscent = 1. * m_ascent * m_font->y_ppem / m_emsquare;
+ if (pDescent) *pDescent = 1. * m_descent * m_font->y_ppem / m_emsquare;
+ if (pEmSquare) *pEmSquare = m_font->x_scale;
+ }
+ virtual void getGlyphPoint(gr::gid16 glyphID, unsigned int pointNum, gr::Point &pointReturn)
+ {
+ hb_position_t x, y;
+ hb_font_get_contour_point(m_font, m_face, pointNum, glyphID, &x, &y);
+ pointReturn.x = (float)x;
+ pointReturn.y = (float)y;
+ }
+
+ virtual void getGlyphMetrics(gr::gid16 glyphID, gr::Rect &boundingBox, gr::Point &advances)
+ {
+ hb_glyph_metrics_t metrics;
+ hb_font_get_glyph_metrics(m_font, m_face, glyphID, &metrics);
+ boundingBox.top = (metrics.y_offset + metrics.height);
+ boundingBox.bottom = metrics.y_offset;
+ boundingBox.left = metrics.x_offset;
+ boundingBox.right = (metrics.x_offset + metrics.width);
+ advances.x = metrics.x_advance;
+ advances.y = metrics.y_advance;
+// fprintf (stderr, "%d: (%d, %d, %d, %d)+(%d, %d)\n", glyphID, metrics.x_offset, metrics.y_offset, metrics.width, metrics.height, metrics.x_advance, metrics.y_advance);
+ }
+
+private:
+ void initfont();
+
+ hb_font_t *m_font;
+ hb_face_t *m_face;
+ float m_ascent;
+ float m_descent;
+ float m_emsquare;
+ bool m_bold;
+ bool m_italic;
+ std::map<hb_tag_t, hb_blob_t *> m_blobs;
+};
+
+void GrHbFont::initfont()
+{
+ const void *pOS2 = getTable(gr::kttiOs2, NULL);
+ const void *pHead = getTable(gr::kttiHead, NULL);
+ TtfUtil::FontOs2Style(pOS2, m_bold, m_italic);
+ m_ascent = static_cast<float>(TtfUtil::FontAscent(pOS2));
+ m_descent = static_cast<float>(TtfUtil::FontDescent(pOS2));
+ m_emsquare = static_cast<float>(TtfUtil::DesignUnits(pHead));
+}
+
+void
+hb_graphite_shape (hb_font_t *font,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ hb_feature_t *features,
+ unsigned int num_features)
+{
+ /* create text source */
+ GrBufferTextSrc textSrc(buffer, features, num_features);
+
+ /* create grfont */
+ GrHbFont grfont(font, face);
+
+ /* create segment */
+ int *firsts;
+ bool *flags;
+ int numChars;
+ int numGlyphs;
+ gr::LayoutEnvironment layout;
+ std::pair<gr::GlyphIterator, gr::GlyphIterator>glyph_range;
+ gr::GlyphIterator iGlyph;
+ hb_codepoint_t *glyph_infos, *pGlyph;
+ hb_glyph_position_t *pPosition;
+ int cGlyph = 0;
+ int cChar = 0;
+
+ layout.setStartOfLine(0);
+ layout.setEndOfLine(0);
+ layout.setDumbFallback(true);
+ layout.setJustifier(NULL);
+ layout.setRightToLeft(false);
+
+ gr::RangeSegment pSegment(&grfont, &textSrc, &layout, (gr::toffset)0,
+ static_cast<gr::toffset>(buffer->len), (gr::Segment *)NULL);
+
+ /* fill in buffer from segment */
+ _hb_buffer_clear_output(buffer);
+ pSegment.getUniscribeClusters(NULL, 0, &numChars, NULL, 0, &numGlyphs);
+ firsts = new int[numChars];
+ flags = new bool[numGlyphs];
+ glyph_infos = new hb_codepoint_t[numGlyphs];
+ hb_buffer_ensure(buffer, numGlyphs);
+ pSegment.getUniscribeClusters(firsts, numChars, NULL, flags, numGlyphs, NULL);
+ glyph_range = pSegment.glyphs();
+ for (pGlyph = glyph_infos, iGlyph = glyph_range.first; iGlyph != glyph_range.second;
+ iGlyph++, pGlyph++)
+ { *pGlyph = iGlyph->glyphID(); }
+
+ while (cGlyph < numGlyphs)
+ {
+ if (flags[cGlyph])
+ {
+ int oldcChar = cChar++;
+ int oldcGlyph = cGlyph++;
+ while (cChar < numChars && firsts[cChar] == firsts[oldcChar]) cChar++;
+ while (cGlyph < numGlyphs && !flags[cGlyph]) cGlyph++;
+ _hb_buffer_add_output_glyphs(buffer, cChar - oldcChar, cGlyph - oldcGlyph,
+ glyph_infos + oldcGlyph, 0xFFFF, 0xFFFF);
+ }
+ else
+ { cGlyph++; } /* This should never happen */
+ }
+
+ float curradvx = 0., curradvy = 0.;
+ for (pPosition = hb_buffer_get_glyph_positions(buffer), iGlyph = glyph_range.first;
+ iGlyph != glyph_range.second; pPosition++, iGlyph++)
+ {
+ pPosition->x_offset = iGlyph->origin() - curradvx;
+ pPosition->y_offset = iGlyph->yOffset() - curradvy;
+ pPosition->x_advance = pPosition->x_offset + iGlyph->advanceWidth();
+ pPosition->y_advance = pPosition->y_offset + iGlyph->advanceHeight();
+// if (pPosition->x_advance < 0)
+// pPosition->x_advance = 0;
+ curradvx += pPosition->x_advance;
+ curradvy += pPosition->y_advance;
+// fprintf(stderr, "%d@(%f, %f)+(%f, %f)\n", iGlyph->glyphID(), iGlyph->origin(), iGlyph->yOffset(), iGlyph->advanceWidth(), iGlyph->advanceHeight());
+ }
+
+ delete[] glyph_infos;
+ delete[] firsts;
+ delete[] flags;
+}
diff --git a/src/hb-graphite.h b/src/hb-graphite.h
new file mode 100644
index 0000000..ac9ca27
--- /dev/null
+++ b/src/hb-graphite.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009, Martin Hosken
+ * Copyright (C) 2009, SIL International
+ *
+ * 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_GRAPHITE_H
+#define HB_GRAPHITE_H
+
+#include "hb-shape.h"
+
+
+HB_BEGIN_DECLS
+
+#define HB_GRAPHITE_TAG_Silf HB_TAG('S','i','l','f')
+
+void hb_graphite_shape (hb_font_t *font,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ hb_feature_t *features,
+ unsigned int num_features);
+
+HB_END_DECLS
+
+#endif /* HB_GRAPHITE_H */
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index b77677c..a53f3ea 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -32,6 +32,9 @@
#include "hb-ot-shape-private.hh"
+#ifdef HAVE_GRAPHITE
+#include "hb-graphite.h"
+#endif
/* Prepare */
@@ -220,6 +223,18 @@ hb_shape (hb_font_t *font,
hb_direction_t original_direction;
hb_bool_t substitute_fallback, position_fallback;
+#ifdef HAVE_GRAPHITE
+ hb_blob_t *silf_blob;
+ silf_blob = hb_face_get_table (face, HB_GRAPHITE_TAG_Silf);
+ if (hb_blob_get_length(silf_blob))
+ {
+ hb_graphite_shape(font, face, buffer, features, num_features);
+ hb_blob_destroy(silf_blob);
+ return;
+ }
+ hb_blob_destroy(silf_blob);
+#endif
+
hb_form_clusters (buffer);
hb_substitute_default (font, face, buffer, features, num_features);
commit 3ba6818ba9be950e46902f0239f2451ec0e65d44
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 13:51:29 2010 +0100
Update the Python module
diff --git a/contrib/python/lib/harfbuzz.pyx b/contrib/python/lib/harfbuzz.pyx
index 1f254ff..2a97c6c 100644
--- a/contrib/python/lib/harfbuzz.pyx
+++ b/contrib/python/lib/harfbuzz.pyx
@@ -7,7 +7,7 @@ cdef extern from "ft2build.h" :
pass
cdef extern from "freetype/freetype.h" :
- ctypedef void *FT_Library
+ ctypedef void *FT_Library
ctypedef void *FT_Face
ctypedef int FT_Error
@@ -27,6 +27,7 @@ cdef extern from "hb-common.h" :
ctypedef long hb_position_t
ctypedef unsigned long hb_mask_t
ctypedef unsigned long hb_tag_t
+ hb_tag_t hb_tag_from_string (char *s)
ctypedef void (*hb_destroy_func_t) (void *user_data)
cdef extern from "hb-unicode.h" :
@@ -113,6 +114,22 @@ cdef extern from "hb-unicode.h" :
HB_SCRIPT_CARIAN,
HB_SCRIPT_LYCIAN,
HB_SCRIPT_LYDIAN
+# Unicode-5.2
+ HB_SCRIPT_AVESTAN
+ HB_SCRIPT_BAMUM
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS
+ HB_SCRIPT_IMPERIAL_ARAMAIC
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN
+ HB_SCRIPT_JAVANESE
+ HB_SCRIPT_KAITHI
+ HB_SCRIPT_LISU
+ HB_SCRIPT_MEITEI_MAYEK
+ HB_SCRIPT_OLD_SOUTH_ARABIAN
+ HB_SCRIPT_OLD_TURKIC
+ HB_SCRIPT_SAMARITAN
+ HB_SCRIPT_TAI_THAM
+ HB_SCRIPT_TAI_VIET
cdef extern from "hb-language.h" :
ctypedef void *hb_language_t
@@ -120,7 +137,7 @@ cdef extern from "hb-language.h" :
char * hb_language_to_string(hb_language_t language)
cdef extern from "hb-ot-tag.h" :
- hb_script_t hb_ot_string_to_script (char *sname)
+ hb_script_t hb_ot_tag_to_script (char *sname)
cdef extern from "hb-buffer.h" :
ctypedef struct hb_buffer_t :
@@ -178,7 +195,6 @@ cdef extern from "hb-font.h" :
void hb_face_destroy(hb_face_t *face)
void hb_font_destroy(hb_font_t *font)
hb_blob_t * hb_face_get_table(hb_face_t *face, hb_tag_t tag)
- void hb_font_set_tracecallback(hb_font_t *font, void (*cb)(char *type, int index, hb_buffer_t *))
cdef extern from "hb-shape.h" :
@@ -208,10 +224,6 @@ class glyphinfo :
if self.internal : res += "/i=" + str(self.internal)
return res
-gcb = None
-cdef void hb_python_trace(char *aType, int i, hb_buffer_t *aBuffer) :
- gcb(aType, i)
-
cdef class buffer :
cdef hb_buffer_t *buffer
@@ -260,10 +272,8 @@ cdef class ft :
cdef FT_Face face
cdef hb_face_t *hbface
cdef hb_font_t *hbfont
- cdef object tracefn
- def __init__(self, char *fname, size, trace = None) :
- global gcb
+ def __init__(self, char *fname, size) :
cdef FT_Library engine
FT_Init_FreeType(&engine)
self.engine = engine
@@ -273,13 +283,6 @@ cdef class ft :
self.face = face
self.hbface = hb_ft_face_create(face, <void (*)(void *)>hb_face_destroy)
self.hbfont = hb_ft_font_create(face, <void (*)(void *)>hb_font_destroy)
- if trace :
- self.tracefn = trace
- gcb = self.trace
- hb_font_set_tracecallback(self.hbfont, hb_python_trace)
-
- def trace(self, aType, index) :
- self.tracefn(self, aType, index)
def __del__(self) :
cdef FT_Library engine
@@ -295,8 +298,7 @@ cdef class ft :
feats = <hb_feature_t *>malloc(sizeof(hb_feature_t) * len(features))
aFeat = feats
for k,v in features.items() :
- k = k + " "
- aFeat.tag = (ord(k[0]) << 24) + (ord(k[1]) << 16) + (ord(k[2]) << 8) + ord(k[3])
+ aFeat.tag = hb_tag_from_string (k)
aFeat.value = int(v)
aFeat.start = 0
aFeat.end = -1
commit 83f34677bcbc6bb194940407b0fcb23575650e3d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 13:43:49 2010 +0100
Add hb_tag_from_string()
diff --git a/src/Makefile.am b/src/Makefile.am
index fb82f0e..70cbfd8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,7 @@ HBSOURCES = \
hb-blob-private.h \
hb-buffer.cc \
hb-buffer-private.hh \
+ hb-common.c \
hb-font.cc \
hb-font-private.hh \
hb-object-private.h \
diff --git a/src/hb-common.c b/src/hb-common.c
new file mode 100644
index 0000000..d205fc8
--- /dev/null
+++ b/src/hb-common.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Red Hat, 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.h"
+
+hb_tag_t
+hb_tag_from_string (const char *s)
+{
+ char tag[4];
+ unsigned int i;
+
+ for (i = 0; i < 4 && s[i]; i++)
+ tag[i] = s[i];
+ for (; i < 4; i++)
+ tag[i] = ' ';
+
+ return HB_TAG_STR (tag);
+}
diff --git a/src/hb-common.h b/src/hb-common.h
index 594d358..74d8512 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -65,6 +65,9 @@ typedef uint32_t hb_tag_t;
((const char *) s)[3]))
#define HB_TAG_NONE HB_TAG(0,0,0,0)
+hb_tag_t hb_tag_from_string (const char *s);
+
+
typedef uint32_t hb_codepoint_t;
typedef int32_t hb_position_t;
typedef uint32_t hb_mask_t;
commit 4a9a5c0b06e8aa5d15327242609a7c766d3e0e94
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 13:33:46 2010 +0100
Don't allocate bits for features not available
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 84f3432..8e5d6d8 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -125,6 +125,11 @@ setup_lookups (hb_face_t *face,
unsigned int global_values = 0;
for (i = 0; i < num_features; i++)
{
+ if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
+ features[i].tag,
+ &feature_index))
+ continue;
+
unsigned int bits_needed = _hb_bit_storage (features[i].value);
if (!bits_needed)
continue;
@@ -132,10 +137,7 @@ setup_lookups (hb_face_t *face,
unsigned int value = features[i].value << last_bit_used;
last_bit_used += bits_needed;
- if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
- features[i].tag,
- &feature_index))
- add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups);
+ add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups);
if (features[i].start == 0 && features[i].end == (unsigned int)-1)
global_values |= value;
commit e53d77142ac4ecbe38ab3235491fa93cb7ff16ab
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 13:32:38 2010 +0100
Speed up feature mask setting
Patch from Jonathan Kew.
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 6a8c7ec..84f3432 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -122,6 +122,7 @@ setup_lookups (hb_face_t *face,
buffer->info[i].mask = 1;
unsigned int last_bit_used = 1;
+ unsigned int global_values = 0;
for (i = 0; i < num_features; i++)
{
unsigned int bits_needed = _hb_bit_storage (features[i].value);
@@ -136,15 +137,33 @@ setup_lookups (hb_face_t *face,
&feature_index))
add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups);
- /* Turn mask on in the buffer, the über-slow way! */
- unsigned int count = buffer->len;
- for (unsigned int j = 0; j < count; j++) {
- unsigned int cluster = buffer->info[j].cluster;
- if (features[i].start <= cluster && cluster < features[i].end)
- buffer->info[j].mask |= value;
+ if (features[i].start == 0 && features[i].end == (unsigned int)-1)
+ global_values |= value;
+ else
+ {
+ unsigned int start = features[i].start, end = features[i].end;
+ unsigned int a = 0, b = buffer->len;
+ while (a < b)
+ {
+ unsigned int h = a + ((b - a) / 2);
+ if (buffer->info[h].cluster < start)
+ a = h + 1;
+ else
+ b = h;
+ }
+ unsigned int count = buffer->len;
+ for (unsigned int j = a; j < count && buffer->info[j].cluster < end; j++)
+ buffer->info[j].mask |= value;
}
}
+ if (global_values)
+ {
+ unsigned int count = buffer->len;
+ for (unsigned int j = 0; j < count; j++)
+ buffer->info[j].mask |= global_values;
+ }
+
qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);
if (*num_lookups)
commit 4fa67f34ecc65056ce60a572213fbdae66e0423b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 13:29:12 2010 +0100
Add Unicode 5.2 scripts
diff --git a/src/hb-icu.c b/src/hb-icu.c
index 8e4ef94..2d1ef85 100644
--- a/src/hb-icu.c
+++ b/src/hb-icu.c
@@ -31,6 +31,7 @@
#include "hb-unicode-private.h"
+#include <unicode/uversion.h>
#include <unicode/uchar.h>
#include <unicode/uscript.h>
@@ -110,9 +111,12 @@ hb_icu_get_script (hb_codepoint_t unicode)
UScriptCode scriptCode = uscript_getScript(unicode, &status);
switch ((int) scriptCode)
{
+#define CHECK_ICU_VERSION(major, minor) \
+ U_ICU_VERSION_MAJOR_NUM > (major) || (U_ICU_VERSION_MAJOR_NUM == (major) && U_ICU_VERSION_MINOR_NUM >= (minor))
#define MATCH_SCRIPT(C) case USCRIPT_##C: return HB_SCRIPT_##C
+#define MATCH_SCRIPT2(C1, C2) case USCRIPT_##C1: return HB_SCRIPT_##C2
MATCH_SCRIPT (INVALID_CODE);
- MATCH_SCRIPT (COMMON); /* Zyyy */
+ MATCH_SCRIPT (COMMON); /* Zyyy */
MATCH_SCRIPT (INHERITED); /* Qaai */
MATCH_SCRIPT (ARABIC); /* Arab */
MATCH_SCRIPT (ARMENIAN); /* Armn */
@@ -198,6 +202,29 @@ hb_icu_get_script (hb_codepoint_t unicode)
MATCH_SCRIPT (CARIAN); /* Cari */
MATCH_SCRIPT (LYCIAN); /* Lyci */
MATCH_SCRIPT (LYDIAN); /* Lydi */
+
+ /* Unicode-5.2 additions */
+ MATCH_SCRIPT (AVESTAN); /* Avst */
+#if CHECK_ICU_VERSION (4, 4)
+ MATCH_SCRIPT (BAMUM); /* Bamu */
+#endif
+ MATCH_SCRIPT (EGYPTIAN_HIEROGLYPHS); /* Egyp */
+ MATCH_SCRIPT (IMPERIAL_ARAMAIC); /* Armi */
+ MATCH_SCRIPT (INSCRIPTIONAL_PAHLAVI); /* Phli */
+ MATCH_SCRIPT (INSCRIPTIONAL_PARTHIAN); /* Prti */
+ MATCH_SCRIPT (JAVANESE); /* Java */
+ MATCH_SCRIPT (KAITHI); /* Kthi */
+ MATCH_SCRIPT2(LANNA, TAI_THAM); /* Lana */
+#if CHECK_ICU_VERSION (4, 4)
+ MATCH_SCRIPT (LISU); /* Lisu */
+#endif
+ MATCH_SCRIPT (MEITEI_MAYEK); /* Mtei */
+#if CHECK_ICU_VERSION (4, 4)
+ MATCH_SCRIPT (OLD_SOUTH_ARABIAN); /* Sarb */
+#endif
+ MATCH_SCRIPT2(ORKHON, OLD_TURKIC); /* Orkh */
+ MATCH_SCRIPT (SAMARITAN); /* Samr */
+ MATCH_SCRIPT (TAI_VIET); /* Tavt */
}
return HB_SCRIPT_UNKNOWN;
}
diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index a77fef8..d1d42f5 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -120,7 +120,24 @@ static const hb_tag_t ot_scripts[][3] = {
{HB_TAG('v','a','i',' ')}, /* HB_SCRIPT_VAI */
{HB_TAG('c','a','r','i')}, /* HB_SCRIPT_CARIAN */
{HB_TAG('l','y','c','i')}, /* HB_SCRIPT_LYCIAN */
- {HB_TAG('l','y','d','i')} /* HB_SCRIPT_LYDIAN */
+ {HB_TAG('l','y','d','i')}, /* HB_SCRIPT_LYDIAN */
+
+ /* Unicode-5.2 additions */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_AVESTAN */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_BAMUM */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_EGYPTIAN_HIEROGLYPHS */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_IMPERIAL_ARAMAIC */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_INSCRIPTIONAL_PAHLAVI */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_INSCRIPTIONAL_PARTHIAN */
+ {HB_TAG('j','a','v','a')}, /* HB_SCRIPT_JAVANESE */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_KAITHI */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_LISU */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_MEITEI_MAYEK */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_OLD_SOUTH_ARABIAN */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_OLD_TURKIC */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_SAMARITAN */
+ {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_TAI_THAM */
+ {HB_TAG('D','F','L','T')} /* HB_SCRIPT_TAI_VIET */
};
const hb_tag_t *
@@ -140,7 +157,7 @@ hb_ot_tag_to_script (hb_tag_t tag)
int i;
for (i = 0; i < ARRAY_LENGTH (ot_scripts); i++) {
- hb_tag_t *p = ot_scripts[i];
+ const hb_tag_t *p = ot_scripts[i];
while (*p)
if (tag == *p)
return i;
diff --git a/src/hb-unicode.c b/src/hb-unicode.c
index 7970a79..1813940 100644
--- a/src/hb-unicode.c
+++ b/src/hb-unicode.c
@@ -286,7 +286,24 @@ const hb_direction_t horiz_dir[] =
LTR, /* Vaii */
LTR, /* Cari */
LTR, /* Lyci */
- LTR /* Lydi */
+ LTR, /* Lydi */
+
+ /* Unicode-5.2 additions */
+ RTL, /* Avst */
+ LTR, /* Bamu */
+ LTR, /* Egyp */
+ RTL, /* Armi */
+ RTL, /* Phli */
+ RTL, /* Prti */
+ LTR, /* Java */
+ LTR, /* Kthi */
+ LTR, /* Lisu */
+ LTR, /* Mtei */
+ RTL, /* Sarb */
+ RTL, /* Orkh */
+ RTL, /* Samr */
+ LTR, /* Lana */
+ LTR /* Tavt */
};
#undef LTR
#undef RTL
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index dc70bd1..2f4f69b 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -155,7 +155,24 @@ typedef enum
HB_SCRIPT_VAI, /* Vaii */
HB_SCRIPT_CARIAN, /* Cari */
HB_SCRIPT_LYCIAN, /* Lyci */
- HB_SCRIPT_LYDIAN /* Lydi */
+ HB_SCRIPT_LYDIAN, /* Lydi */
+
+ /* Unicode-5.2 additions */
+ HB_SCRIPT_AVESTAN, /* Avst */
+ HB_SCRIPT_BAMUM, /* Bamu */
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, /* Egyp */
+ HB_SCRIPT_IMPERIAL_ARAMAIC, /* Armi */
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, /* Phli */
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, /* Prti */
+ HB_SCRIPT_JAVANESE, /* Java */
+ HB_SCRIPT_KAITHI, /* Kthi */
+ HB_SCRIPT_LISU, /* Lisu */
+ HB_SCRIPT_MEITEI_MAYEK, /* Mtei */
+ HB_SCRIPT_OLD_SOUTH_ARABIAN, /* Sarb */
+ HB_SCRIPT_OLD_TURKIC, /* Orkh */
+ HB_SCRIPT_SAMARITAN, /* Samr */
+ HB_SCRIPT_TAI_THAM, /* Lana */
+ HB_SCRIPT_TAI_VIET /* Tavt */
} hb_script_t;
commit ee1b322100a6bd575b999904592abbd9fed5587f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 12:55:57 2010 +0100
Fix feature mask setting
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 509ce7d..6a8c7ec 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -138,10 +138,10 @@ setup_lookups (hb_face_t *face,
/* Turn mask on in the buffer, the über-slow way! */
unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++) {
- unsigned int cluster = buffer->info[i].cluster;
+ for (unsigned int j = 0; j < count; j++) {
+ unsigned int cluster = buffer->info[j].cluster;
if (features[i].start <= cluster && cluster < features[i].end)
- buffer->info[i].mask |= value;
+ buffer->info[j].mask |= value;
}
}
commit b490fa343322f1b5abaf880abc073287c1f34132
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 11:15:07 2010 +0100
Add hb_ot_tag_to_script()
diff --git a/src/hb-ot-tag.c b/src/hb-ot-tag.c
index fc4889b..a77fef8 100644
--- a/src/hb-ot-tag.c
+++ b/src/hb-ot-tag.c
@@ -134,6 +134,20 @@ hb_ot_tags_from_script (hb_script_t script)
return ot_scripts[script];
}
+hb_script_t
+hb_ot_tag_to_script (hb_tag_t tag)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_LENGTH (ot_scripts); i++) {
+ hb_tag_t *p = ot_scripts[i];
+ while (*p)
+ if (tag == *p)
+ return i;
+ }
+
+ return HB_SCRIPT_UNKNOWN;
+}
typedef struct {
char language[6];
diff --git a/src/hb-ot-tag.h b/src/hb-ot-tag.h
index 2dab2e8..6d15d4e 100644
--- a/src/hb-ot-tag.h
+++ b/src/hb-ot-tag.h
@@ -38,6 +38,9 @@ HB_BEGIN_DECLS
const hb_tag_t *
hb_ot_tags_from_script (hb_script_t script);
+hb_script_t
+hb_ot_tag_to_script (hb_tag_t tag);
+
hb_tag_t
hb_ot_tag_from_language (hb_language_t language);
commit 50355309047765558ef8f5d60aefed42a7f954cc
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 21 10:33:23 2010 +0100
Add Python wrapper from Martin Hosken
diff --git a/contrib/python/lib/harfbuzz.pyx b/contrib/python/lib/harfbuzz.pyx
new file mode 100644
index 0000000..1f254ff
--- /dev/null
+++ b/contrib/python/lib/harfbuzz.pyx
@@ -0,0 +1,306 @@
+cdef extern from "stdlib.h":
+ ctypedef int size_t
+ void *malloc(size_t size)
+ void free(void* ptr)
+
+cdef extern from "ft2build.h" :
+ pass
+
+cdef extern from "freetype/freetype.h" :
+ ctypedef void *FT_Library
+ ctypedef void *FT_Face
+ ctypedef int FT_Error
+
+ FT_Error FT_Init_FreeType (FT_Library *alib)
+ FT_Error FT_Done_FreeType (FT_Library alib)
+ FT_Error FT_Done_Face (FT_Face alib)
+ FT_Error FT_New_Face( FT_Library library, char *path, unsigned long index, FT_Face *aface)
+ FT_Error FT_Set_Char_Size (FT_Face aFace, unsigned int size_x, unsigned int size_y, unsigned int res_x, unsigned int res_y)
+
+cdef extern from "hb-common.h" :
+ cdef enum hb_direction_t :
+ HB_DIRECTION_LTR
+ HB_DIRECTION_RTL
+ HB_DIRECTION_TTB
+ HB_DIRECTION_BTT
+ ctypedef unsigned long hb_codepoint_t
+ ctypedef long hb_position_t
+ ctypedef unsigned long hb_mask_t
+ ctypedef unsigned long hb_tag_t
+ ctypedef void (*hb_destroy_func_t) (void *user_data)
+
+cdef extern from "hb-unicode.h" :
+# there must be a better way of syncing this list with the true source
+ ctypedef enum hb_script_t :
+ HB_SCRIPT_INVALID_CODE = -1,
+ HB_SCRIPT_COMMON = 0,
+ HB_SCRIPT_INHERITED,
+ HB_SCRIPT_ARABIC,
+ HB_SCRIPT_ARMENIAN,
+ HB_SCRIPT_BENGALI,
+ HB_SCRIPT_BOPOMOFO,
+ HB_SCRIPT_CHEROKEE,
+ HB_SCRIPT_DESERET,
+ HB_SCRIPT_DEVANAGARI,
+ HB_SCRIPT_ETHIOPIC,
+ HB_SCRIPT_GEORGIAN,
+ HB_SCRIPT_GOTHIC,
+ HB_SCRIPT_GREEK,
+ HB_SCRIPT_GUJARATI,
+ HB_SCRIPT_GURMUKHI,
+ HB_SCRIPT_HAN,
+ HB_SCRIPT_HANGUL,
+ HB_SCRIPT_HEBREW,
+ HB_SCRIPT_HIRAGANA,
+ HB_SCRIPT_KANNADA,
+ HB_SCRIPT_KATAKANA,
+ HB_SCRIPT_KHMER,
+ HB_SCRIPT_LAO,
+ HB_SCRIPT_LATIN,
+ HB_SCRIPT_MALAYALAM,
+ HB_SCRIPT_MONGOLIAN,
+ HB_SCRIPT_MYANMAR,
+ HB_SCRIPT_OGHAM,
+ HB_SCRIPT_OLD_ITALIC,
+ HB_SCRIPT_ORIYA,
+ HB_SCRIPT_RUNIC,
+ HB_SCRIPT_SINHALA,
+ HB_SCRIPT_SYRIAC,
+ HB_SCRIPT_TAMIL,
+ HB_SCRIPT_TELUGU,
+ HB_SCRIPT_THAANA,
+ HB_SCRIPT_THAI,
+ HB_SCRIPT_TIBETAN,
+ HB_SCRIPT_CANADIAN_ABORIGINAL,
+ HB_SCRIPT_YI,
+ HB_SCRIPT_TAGALOG,
+ HB_SCRIPT_HANUNDO,
+ HB_SCRIPT_BUHID,
+ HB_SCRIPT_TAGBANWA,
+# Unicode 4.0
+ HB_SCRIPT_BRAILLE,
+ HB_SCRIPT_CYPRIOT,
+ HB_SCRIPT_LIMBU,
+ HB_SCRIPT_OSMANYA,
+ HB_SCRIPT_SHAVIAN,
+ HB_SCRIPT_LINEAR_B,
+ HB_SCRIPT_TAI_LE,
+ HB_SCRIPT_UGARITIC,
+# Unicode 4.1
+ HB_SCRIPT_NEW_TAI_LUE,
+ HB_SCRIPT_BUGINESE,
+ HB_SCRIPT_GLAGOLITIC,
+ HB_SCRIPT_TIFINAGH,
+ HB_SCRIPT_SYLOTI_NAGRI,
+ HB_SCRIPT_OLD_PERSIAN,
+ HB_SCRIPT_KHAROSHTHI,
+# Unicode 5.0
+ HB_SCRIPT_UNKNOWN,
+ HB_SCRIPT_BALINESE,
+ HB_SCRIPT_CUNEIFORM,
+ HB_SCRIPT_PHOENICIAN,
+ HB_SCRIPT_PHAGS_PA,
+ HB_SCRIPT_NKO,
+# Unicode 5.1
+ HB_SCRIPT_KAYAH_LI,
+ HB_SCRIPT_LEPCHA,
+ HB_SCRIPT_REJANG,
+ HB_SCRIPT_SUNDANESE,
+ HB_SCRIPT_SAURASHTRA,
+ HB_SCRIPT_CHAM,
+ HB_SCRIPT_OL_CHIKI,
+ HB_SCRIPT_VAI,
+ HB_SCRIPT_CARIAN,
+ HB_SCRIPT_LYCIAN,
+ HB_SCRIPT_LYDIAN
+
+cdef extern from "hb-language.h" :
+ ctypedef void *hb_language_t
+ hb_language_t hb_language_from_string(char *str)
+ char * hb_language_to_string(hb_language_t language)
+
+cdef extern from "hb-ot-tag.h" :
+ hb_script_t hb_ot_string_to_script (char *sname)
+
+cdef extern from "hb-buffer.h" :
+ ctypedef struct hb_buffer_t :
+ pass
+
+ ctypedef struct hb_glyph_info_t :
+ hb_codepoint_t codepoint
+ hb_mask_t mask
+ unsigned long cluster
+
+ ctypedef struct hb_glyph_position_t :
+ hb_position_t x_advance
+ hb_position_t y_advance
+ hb_position_t x_offset
+ hb_position_t y_offset
+ unsigned long internal
+
+ hb_buffer_t *hb_buffer_create(unsigned int size)
+ hb_buffer_t *hb_buffer_reference(hb_buffer_t *buffer)
+ unsigned int hb_buffer_get_reference_count(hb_buffer_t *buffer)
+ void hb_buffer_destroy(hb_buffer_t *buffer)
+ void hb_buffer_set_direction(hb_buffer_t *buffer, hb_direction_t direction)
+ hb_direction_t hb_buffer_get_direction(hb_buffer_t *buffer)
+ void hb_buffer_set_script(hb_buffer_t *buffer, hb_script_t script)
+ hb_script_t hb_buffer_get_script(hb_buffer_t *buffer)
+ void hb_buffer_set_language(hb_buffer_t *buffer, hb_language_t language)
+ hb_language_t hb_buffer_get_language(hb_buffer_t *buffer)
+ void hb_buffer_clear(hb_buffer_t *)
+ void hb_buffer_clear_positions(hb_buffer_t *buffer)
+ void hb_buffer_ensure(hb_buffer_t *buffer, unsigned int size)
+ void hb_buffer_reverse(hb_buffer_t *buffer)
+ void hb_buffer_reverse_clusters(hb_buffer_t *buffer)
+ void hb_buffer_add_glyph(hb_buffer_t *buffer, hb_codepoint_t codepoint, hb_mask_t mask, unsigned int cluster)
+ void hb_buffer_add_utf8(hb_buffer_t *buffer, char *text, unsigned int text_length, unsigned int item_offset, unsigned int item_length)
+ unsigned int hb_buffer_get_length(hb_buffer_t *buffer)
+ hb_glyph_info_t *hb_buffer_get_glyph_infos(hb_buffer_t *buffer)
+ hb_glyph_position_t *hb_buffer_get_glyph_positions(hb_buffer_t *buffer)
+
+cdef extern from "hb-blob.h" :
+ cdef struct hb_blob_t :
+ pass
+# do I need blob functions here?
+
+cdef extern from "hb-font.h" :
+ ctypedef struct hb_face_t :
+ pass
+ ctypedef struct hb_font_t :
+ pass
+
+ ctypedef hb_blob_t * (*hb_get_table_func_t) (hb_tag_t tag, void *user_data)
+ hb_face_t * hb_face_create_for_data(hb_blob_t *blob, unsigned int index)
+ hb_face_t * hb_face_create_for_tables(hb_get_table_func_t get_table, hb_destroy_func_t destroy, void *user_data)
+ hb_face_t * hb_face_reference(hb_face_t *face)
+ unsigned int hb_face_get_reference_count(hb_face_t *face)
+ void hb_face_destroy(hb_face_t *face)
+ void hb_font_destroy(hb_font_t *font)
+ hb_blob_t * hb_face_get_table(hb_face_t *face, hb_tag_t tag)
+ void hb_font_set_tracecallback(hb_font_t *font, void (*cb)(char *type, int index, hb_buffer_t *))
+
+
+cdef extern from "hb-shape.h" :
+ ctypedef struct hb_feature_t :
+ int tag
+ unsigned int value
+ unsigned int start
+ unsigned int end
+
+ void hb_shape (hb_font_t *font, hb_face_t *face, hb_buffer_t *buffer, hb_feature_t *features, unsigned int num_features)
+
+cdef extern from "hb-ft.h" :
+ hb_face_t *hb_ft_face_create (FT_Face ft_face, hb_destroy_func_t destroy)
+ hb_font_t *hb_ft_font_create (FT_Face ft_face, hb_destroy_func_t destroy)
+
+class glyphinfo :
+
+ def __init__(self, gid, cluster, advance, offset, internal = 0) :
+ self.gid = gid
+ self.cluster = cluster
+ self.advance = advance
+ self.offset = offset
+ self.internal = internal
+
+ def __repr__(self) :
+ res = "{0:d}>{1:d}@({2:.2f},{3:.2f})+({4:.2f},{5:.2f})".format(self.gid, self.cluster, self.offset[0], self.offset[1], self.advance[0], self.advance[1])
+ if self.internal : res += "/i=" + str(self.internal)
+ return res
+
+gcb = None
+cdef void hb_python_trace(char *aType, int i, hb_buffer_t *aBuffer) :
+ gcb(aType, i)
+
+cdef class buffer :
+ cdef hb_buffer_t *buffer
+
+ def __init__(self, char *text, unsigned int length) :
+ """Note text must be a utf-8 string and length is number of chars"""
+ self.buffer = hb_buffer_create(length)
+ hb_buffer_add_utf8(self.buffer, text, length, 0, len(text))
+
+ def set_scriptlang(self, char *script, char *lang) :
+ cdef hb_language_t language
+ cdef hb_script_t scriptnum
+
+ language = hb_language_from_string(lang)
+ scriptnum = hb_ot_string_to_script(script)
+ hb_buffer_set_script(self.buffer, scriptnum)
+ hb_buffer_set_language(self.buffer, language)
+
+ def get_info(self, scale = 1) :
+ cdef hb_glyph_info_t *infos
+ cdef hb_glyph_position_t *positions
+ cdef unsigned int num
+ cdef unsigned int i
+ res = []
+
+ num = hb_buffer_get_length(self.buffer)
+ infos = hb_buffer_get_glyph_infos(self.buffer)
+ positions = hb_buffer_get_glyph_positions(self.buffer)
+ for 0 <= i < num :
+ temp = glyphinfo(infos[i].codepoint, infos[i].cluster, (positions[i].x_advance / scale, positions[i].y_advance / scale), (positions[i].x_offset / scale, positions[i].y_offset / scale), positions[i].internal)
+ res.append(temp)
+ return res
+
+ def get_settings(self) :
+ cdef hb_script_t script
+ cdef hb_language_t lang
+
+ script = hb_buffer_get_script(self.buffer)
+ lang = hb_buffer_get_language(self.buffer)
+ return {'script' : script, 'language' : hb_language_to_string(lang)}
+
+ def __del__(self) :
+ hb_buffer_destroy(self.buffer)
+
+cdef class ft :
+ cdef FT_Library engine
+ cdef FT_Face face
+ cdef hb_face_t *hbface
+ cdef hb_font_t *hbfont
+ cdef object tracefn
+
+ def __init__(self, char *fname, size, trace = None) :
+ global gcb
+ cdef FT_Library engine
+ FT_Init_FreeType(&engine)
+ self.engine = engine
+ cdef FT_Face face
+ FT_New_Face(engine, fname, 0, &face)
+ FT_Set_Char_Size(face, size << 6, size << 6, 144, 144)
+ self.face = face
+ self.hbface = hb_ft_face_create(face, <void (*)(void *)>hb_face_destroy)
+ self.hbfont = hb_ft_font_create(face, <void (*)(void *)>hb_font_destroy)
+ if trace :
+ self.tracefn = trace
+ gcb = self.trace
+ hb_font_set_tracecallback(self.hbfont, hb_python_trace)
+
+ def trace(self, aType, index) :
+ self.tracefn(self, aType, index)
+
+ def __del__(self) :
+ cdef FT_Library engine
+ engine = self.engine
+ cdef FT_Face face
+ face = self.face
+ FT_Done_Face(face)
+ FT_Done_FreeType(engine)
+
+ def shape(self, buffer aBuffer, features = {}) :
+ cdef hb_feature_t *feats
+ cdef hb_feature_t *aFeat
+ feats = <hb_feature_t *>malloc(sizeof(hb_feature_t) * len(features))
+ aFeat = feats
+ for k,v in features.items() :
+ k = k + " "
+ aFeat.tag = (ord(k[0]) << 24) + (ord(k[1]) << 16) + (ord(k[2]) << 8) + ord(k[3])
+ aFeat.value = int(v)
+ aFeat.start = 0
+ aFeat.end = -1
+ aFeat += 1
+ hb_shape(self.hbfont, self.hbface, aBuffer.buffer, feats, len(features))
+
+
diff --git a/contrib/python/runpy b/contrib/python/runpy
new file mode 100755
index 0000000..b39db1b
--- /dev/null
+++ b/contrib/python/runpy
@@ -0,0 +1,2 @@
+#!/bin/sh
+LD_LIBRARY_PATH=../../src/.libs PYTHONPATH=build/lib.`python -c 'import distutils.util, sys; print distutils.util.get_platform()+"-"+str(sys.version_info[0])+"."+str(sys.version_info[1])'` "$@"
diff --git a/contrib/python/scripts/hbtestfont b/contrib/python/scripts/hbtestfont
new file mode 100755
index 0000000..4d1134d
--- /dev/null
+++ b/contrib/python/scripts/hbtestfont
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import harfbuzz, optparse
+
+buffer = None
+
+def tracefn(ft, aType, index) :
+ print aType + "(" + str(index) + "): " + str(buffer.get_info())
+
+usage = '''usage: %prog [options] fontfile "codepoints"
+ Generates output of glyphs and positions. Each entry is of the form:
+ glyphid>cluster@(offsetx,offsety)+(advancex,advancey)
+
+ codepoints is a space separated list of hex values of Unicode codepoints'''
+p = optparse.OptionParser(usage=usage)
+p.add_option('-s', '--size', default=12, type="int", help="point size")
+p.add_option('-l', '--lang', help="language code")
+p.add_option('-c', '--script', help="script code")
+p.add_option('-f', '--feature', action='append', help="define a feature key=val")
+p.add_option('-d', '--debug', action='store_true', help="Output trace info")
+(opts, args) = p.parse_args()
+
+ft = harfbuzz.ft(args[0], opts.size, trace = tracefn if opts.debug else None)
+text = "".join(unichr(int(c, 16)) for c in args[1].split(" "))
+bytes = text.encode('utf_8')
+buffer = harfbuzz.buffer(bytes, len(text))
+if (opts.lang or opts.script) : buffer.set_scriptlang(opts.script if opts.script else "", opts.lang if opts.lang else "")
+features = {}
+if opts.feature :
+ for f in opts.feature :
+ k, v = f.split("=")
+ features[k] = v
+ft.shape(buffer, features = features)
+res = buffer.get_info(64) # scale for 26.6
+print res
diff --git a/contrib/python/setup.py b/contrib/python/setup.py
new file mode 100755
index 0000000..ef2412b
--- /dev/null
+++ b/contrib/python/setup.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+from distutils.core import setup
+from glob import glob
+from Pyrex.Distutils.extension import Extension
+from Pyrex.Distutils import build_ext
+
+setup(name='harfbuzz',
+ version='0.0.1',
+ description='Harfbuzz compatibility layer',
+ long_description='Harfbuzz python integration modules and supporting scripts',
+ maintainer='Martin Hosken',
+ maintainer_email='martin_hosken at sil.org',
+ packages=['harfbuzz'],
+ ext_modules = [
+ Extension("harfbuzz", ["lib/harfbuzz.pyx"], libraries=["harfbuzz"], library_dirs=["../../src/.libs"], include_dirs=["/usr/include/freetype2", "../../src"])
+ ],
+ cmdclass = {'build_ext' : build_ext},
+ scripts = glob('scripts/*'),
+ license = 'LGPL',
+ platforms = ['Linux', 'Win32', 'Mac OS X'],
+ package_dir = {'harfbuzz' : 'lib'}
+)
+
commit 280af1bddb958ff97cf7ce12fe7ec2b6352e61d0
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu May 20 18:33:35 2010 +0100
Let hb_face_get_table() return NULL if table not found
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 93787c0..a55deb3 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -364,7 +364,7 @@ hb_face_get_table (hb_face_t *face,
blob = face->get_table (tag, face->user_data);
- return likely (blob) ? blob : &_hb_blob_nil;
+ return blob;
}
diff --git a/src/hb-font.h b/src/hb-font.h
index 433d31a..89324fa 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -60,6 +60,7 @@ hb_face_get_reference_count (hb_face_t *face);
void
hb_face_destroy (hb_face_t *face);
+/* Returns NULL if not found */
hb_blob_t *
hb_face_get_table (hb_face_t *face,
hb_tag_t tag);
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 2ab639c..d2fbb21 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -283,6 +283,9 @@ struct Sanitizer
/* TODO is_sane() stuff */
+ if (!blob)
+ return hb_blob_create_empty ();
+
retry:
if (HB_DEBUG_SANITIZE)
fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC);
More information about the HarfBuzz
mailing list