On Sat, Jul 21, 2012 at 03:08:20AM +0200, Khaled Hosny wrote:
> On Fri, Mar 30, 2012 at 03:27:39PM +0100, Caolán McNamara wrote:
> > On Fri, 2012-03-30 at 16:13 +0200, Khaled Hosny wrote:
> > > If there is interest in this, I can try implementing optional HarfBuzz
> > > support next to ICU so we can experiment more with this (though I'm not
> > > the best person to do this, but I can try).
> > 
> > Can't hurt to give it a go anyway. Even epic failure can point the next
> > person in the right way to go. Yeah lacking Indic shaping would be a
> > problem for right now.
> 
> Indic scripts are supported now (git master, not released yet), and
> given HarfBuzz track record, it should even be better than ICU layout
> engine which is essentially put on ventilator (pun intended), so now is
> a good time to experiment, but I didn't manage to try doing it yet.

Here is a very crude, WIP patch. It adds --enable-harfbuzz configure
option, plus some (very broken) harfbuzz layout code, but I can't get
the ENABLE_HARFBUZZ to propagate in and thus can't do any testing
because the code is never compiled. I appreciate any insights on how to
get this to work.

Regards,
 Khaled
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 26676a7..4e0fc20 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -1110,6 +1110,29 @@ endef
 endif # ENABLE_TELEPATHY
 
 
+ifeq ($(ENABLE_HARFBUZZ),TRUE)
+
+define gb_LinkTarget__use_harfbuzz
+$(call gb_LinkTarget_set_include,$(1),\
+	$$(INCLUDE) \
+	$(HARFBUZZ_CFLAGS) \
+)
+
+$(call gb_LinkTarget_add_libs,$(1),\
+	$(HARFBUZZ_LIBS) \
+)
+
+endef
+
+else # !ENABLE_HARFBUZZ
+
+define gb_LinkTarget__use_harfbuzz
+
+endef
+
+endif # ENABLE_HARFBUZZ
+
+
 ifeq ($(SYSTEM_DB),YES)
 
 define gb_LinkTarget__use_berkeleydb
diff --git a/config_host.mk.in b/config_host.mk.in
index 5e24730..3f3bf1f 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -116,6 +116,7 @@ export ENABLE_GSTREAMER=@ENABLE_GSTREAMER@
 export ENABLE_GTK3=@ENABLE_GTK3@
 export ENABLE_GTK=@ENABLE_GTK@
 export ENABLE_GTK_PRINT=@ENABLE_GTK_PRINT@
+export ENABLE_HARFBUZZ=@ENABLE_HARFBUZZ@
 export ENABLE_HEADLESS=@ENABLE_HEADLESS@
 export ENABLE_TDEAB=@ENABLE_TDEAB@
 export ENABLE_TDE=@ENABLE_TDE@
@@ -199,6 +200,8 @@ export GUIBASE=@GUIBASE@
 export GUIBASE_FOR_BUILD=@GUIBASE_FOR_BUILD@
 export GUI_FOR_BUILD=@GUI_FOR_BUILD@
 export GXX_INCLUDE_PATH=@GXX_INCLUDE_PATH@
+export HARFBUZZ_FLAGS=@HARFBUZZ_CFLAGS@
+export HARFBUZZ_LIBS=@HARFBUZZ_LIBS@
 export HAVE_CXX0X=@HAVE_CXX0X@
 export HAVE_GCC_AVX=@HAVE_GCC_AVX@
 export HAVE_GCC_GGDB2=@HAVE_GCC_GGDB2@
diff --git a/configure.in b/configure.in
index 980a2fb..86334ce 100644
--- a/configure.in
+++ b/configure.in
@@ -796,6 +796,11 @@ AC_ARG_ENABLE(gio,
         [Determines whether to use the GIO support.]),
 ,enable_gio=no)
 
+AC_ARG_ENABLE(harfbuzz,
+    AS_HELP_STRING([--enable-harfbuzz],
+        [Determines whether to use HarfBuzz text layout engine.]),
+,enable_harfbuzz=no)
+
 AC_ARG_ENABLE(telepathy,
     AS_HELP_STRING([--enable-telepathy],
         [Determines whether to enable Telepathy for collaboration.]),
@@ -8969,6 +8974,28 @@ AC_SUBST([GTK_PRINT_LIBS])
 
 
 dnl ===================================================================
+dnl Check whether the HarfBuzz libraries are available.
+dnl ===================================================================
+
+ENABLE_HARFBUZZ=""
+HARFBUZZ_CFLAGS=""
+HARFBUZZ_LIBS=""
+
+AC_MSG_CHECKING([whether to enable HarfBuzz support])
+if test "$_os" != "WINNT" -a "$_os" != "Darwin" -a "$enable_harfbuzz" = "yes"; then
+    ENABLE_HARFBUZZ="TRUE"
+    AC_MSG_RESULT([yes])
+    PKG_CHECK_MODULES( HARFBUZZ, harfbuzz >= 0.9.0 )
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(ENABLE_HARFBUZZ)
+AC_SUBST(HARFBUZZ_CFLAGS)
+AC_SUBST(HARFBUZZ_LIBS)
+
+
+dnl ===================================================================
 dnl Check whether the Telepathy libraries are available.
 dnl ===================================================================
 
diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx
index cd6b96c..be327e2 100644
--- a/vcl/generic/glyphs/gcach_layout.cxx
+++ b/vcl/generic/glyphs/gcach_layout.cxx
@@ -35,9 +35,14 @@
 #include <sal/alloca.h>
 #include <rtl/instance.hxx>
 
+#ifdef ENABLE_HARFBUZZ
+#include <hb-ft.h>
+#include <hb-icu.h>
+#else
 #include <layout/LayoutEngine.h>
 #include <layout/LEFontInstance.h>
 #include <layout/LEScripts.h>
+#endif // ENABLE_HARFBUZZ
 
 #include <unicode/uscript.h>
 #include <unicode/ubidi.h>
@@ -156,6 +161,99 @@ bool ServerFontLayoutEngine::operator()( ServerFontLayout& rLayout, ImplLayoutAr
     return true;
 }
 
+#ifdef ENABLE_HARFBUZZ
+class HbLayoutEngine : public ServerFontLayoutEngine
+{
+private:
+
+public:
+                            HbLayoutEngine( ServerFont& );
+    virtual                 ~HbLayoutEngine();
+
+    virtual bool            operator()( ServerFontLayout&, ImplLayoutArgs& );
+};
+
+HbLayoutEngine::HbLayoutEngine( ServerFont& rServerFont )
+:   mrServerFont( rFont )
+{}
+
+HbLayoutEngine::~HbLayoutEngine()
+{}
+
+bool HbLayoutEngine::operator()( ServerFontLayout& rLayout, ImplLayoutArgs& rArgs )
+{
+    ServerFont& rFont = rLayout.GetServerFont();
+    FT_Face aFace = rFont.GetFtFace();
+    Point aNewPos( 0, 0 );
+
+    // allocate temporary arrays, note: round to even
+    int nGlyphCapacity = (3 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos ) | 15) + 1;
+
+    rLayout.Reserve(nGlyphCapacity);
+
+    hb_font_t *aHbFont = hb_ft_font_create (aFace, NULL);
+
+    int x = 0, y = 0;
+    for( int nGlyphCount = 0;; )
+    {
+        int nMinRunPos, nEndRunPos;
+        bool bRightToLeft;
+        if( !rArgs.GetNextRun( &nMinRunPos, &nEndRunPos, &bRightToLeft ) )
+            break;
+
+        int nRunLen = nEndRunPos - nMinRunPos;
+
+        hb_buffer_t *aHbBuffer = hb_buffer_create ();
+        hb_buffer_set_direction (aHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
+        //hb_buffer_set_script (aHbBuffer, hb_script_from_string ("arab"));
+        //hb_buffer_set_language (aHbBuffer, hb_language_from_string ("ar"));
+        hb_buffer_add_utf16 (aHbBuffer, rArgs.mpStr, nRunLen, nMinRunPos, nRunLen);
+        hb_shape (aHbFont, aHbBuffer, NULL, 0);
+
+        int nRunGlyphCount = hb_buffer_get_length (aHbBuffer);
+        hb_glyph_info_t *aHbGlyph = hb_buffer_get_glyph_infos (aHbBuffer, NULL);
+        hb_glyph_position_t *aHbPosition = hb_buffer_get_glyph_positions (aHbBuffer, NULL);
+
+        uint32_t nLastCluster = -1;
+        bool bInCluster = false
+        for ( int i = 0; i < nRunGlyphCount; i++, aHbGlyph++, aHbPosition++ ) {
+            int nCharPos = 0; // XXX
+
+            hb_codepoint_t nGlyphIndex = aHbGlyph->codepoint;
+
+            // XXX
+            uint32_t nCluster = aHbGlyph->cluster;
+            if ( nCluster == nLastCluster )
+                bInCluster = true;
+
+            const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyphIndex );
+            int nGlyphWidth = rGM.GetCharWidth();
+            int nNewWidth = (aHbPosition->x_advance/64);
+
+            long nGlyphFlags = 0;
+            if( bRightToLeft )
+                nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
+            if( bInCluster )
+                nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
+
+            Point aNewPos = Point( x + (aHbPosition->x_offset/64), y - (aHbPosition->y_offset/64) );
+            x += (aHbPosition->x_advance/64);
+
+            GlyphItem aGI( nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nGlyphWidth );
+            aGI.mnNewWidth = nNewWidth;
+
+            rLayout.AppendGlyph( aGI );
+        }
+
+        nGlyphCount += nRunGlyphCount;
+
+        hb_buffer_destroy (aHbBuffer);
+        hb_font_destroy (aHbFont);
+    }
+
+    return true;
+}
+#else
 // =======================================================================
 // bridge to ICU LayoutEngine
 // =======================================================================
@@ -638,13 +736,20 @@ bool IcuLayoutEngine::operator()( ServerFontLayout& rLayout, ImplLayoutArgs& rAr
     return true;
 }
 
+#endif // ENABLE_HARFBUZZ
+
 // =======================================================================
 
 ServerFontLayoutEngine* ServerFont::GetLayoutEngine()
 {
     // find best layout engine for font, platform, script and language
+#ifdef ENABLE_HARFBUZZ
+    if( !mpLayoutEngine && FT_IS_SFNT( maFaceFT ) )
+        mpLayoutEngine = new HbLayoutEngine( *this );
+#else
     if( !mpLayoutEngine && FT_IS_SFNT( maFaceFT ) )
         mpLayoutEngine = new IcuLayoutEngine( *this );
+#endif // ENABLE_HARFBUZZ
     return mpLayoutEngine;
 }
 
_______________________________________________
LibreOffice mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to