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