diff --git a/configure.in b/configure.in index 24f69c553c5..9b1a0933460 100644 --- a/configure.in +++ b/configure.in @@ -965,7 +965,7 @@ MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/modules/libimg/png)' MOZ_JS_LIBS='-L$(LIBXUL_DIST)/bin -lmozjs' DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core' -MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin' +MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(PREFIX)/lib' XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxpcom' LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) -lxul' XPCOM_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) $(XPCOM_FROZEN_LDOPTS)' @@ -4708,6 +4708,7 @@ MOZ_ARG_HEADER(Toolkit Options) OS/2 - cairo-os2 Win32 - cairo-windows WinCE - windows + Gtk2 with DirectFB - cairo-gtk2-dfb * - cairo-gtk2], [ _DEFAULT_TOOLKIT=$enableval ], [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT]) @@ -4715,6 +4716,8 @@ MOZ_ARG_HEADER(Toolkit Options) if test "$_DEFAULT_TOOLKIT" = "photon" \ -o "$_DEFAULT_TOOLKIT" = "cairo-windows" \ -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \ + -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-dfb" \ + -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \ -o "$_DEFAULT_TOOLKIT" = "cairo-beos" \ -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \ -o "$_DEFAULT_TOOLKIT" = "cairo-mac" \ @@ -4724,11 +4727,7 @@ MOZ_ARG_HEADER(Toolkit Options) dnl so ignore everything after the first comma (","). MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"` else - if test "$no_x" != "yes"; then - AC_MSG_ERROR([Toolkit must be cairo-gtk2.]) - else - AC_MSG_ERROR([Toolkit must be $_PLATFORM_DEFAULT_TOOLKIT (if supported).]) - fi + AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).]) fi AC_DEFINE_UNQUOTED(MOZ_DEFAULT_TOOLKIT,"$MOZ_WIDGET_TOOLKIT") @@ -4748,15 +4747,37 @@ cairo-windows) MOZ_GFX_TOOLKIT=cairo ;; -cairo-gtk2) +cairo-gtk2|cairo-gtk2-x11) MOZ_WIDGET_TOOLKIT=gtk2 MOZ_GFX_TOOLKIT=cairo MOZ_ENABLE_GTK2=1 MOZ_ENABLE_XREMOTE=1 + + AC_DEFINE(MOZ_X11) + MOZ_X11=1 + TK_CFLAGS='$(MOZ_GTK2_CFLAGS)' TK_LIBS='$(MOZ_GTK2_LIBS)' AC_DEFINE(MOZ_WIDGET_GTK2) ;; + +cairo-gtk2-dfb) + MOZ_WIDGET_TOOLKIT=gtk2 + MOZ_GFX_TOOLKIT=cairo + MOZ_ENABLE_GTK2=1 + + AC_DEFINE(MOZ_DFB) + MOZ_DFB=1 + + TK_CFLAGS='$(MOZ_GTK2_CFLAGS)' + TK_LIBS='$(MOZ_GTK2_LIBS)' + AC_DEFINE(MOZ_WIDGET_GTK2) + if test "$no_x" != "yes"; then + AC_MSG_WARN([Disabling X when DirectFB is specified.]) + no_x=yes + fi + ;; + cairo-beos) MOZ_WIDGET_TOOLKIT=beos MOZ_GFX_TOOLKIT=cairo @@ -4796,10 +4817,17 @@ if test "$MOZ_ENABLE_XREMOTE"; then fi if test "$COMPILE_ENVIRONMENT"; then -if test "$MOZ_ENABLE_GTK2" -then - PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 gdk-x11-2.0 glib-2.0 gobject-2.0) -fi + if test "$MOZ_ENABLE_GTK2"; then + if test "$MOZ_X11"; then + GDK_PACKAGES=gdk-x11-2.0 + elif test "$MOZ_DFB"; then + PKG_CHECK_MODULES(MOZ_DFB, directfb >= 1.1.0) + GDK_PACKAGES=directfb + fi + + PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 gobject-2.0 $GDK_PACKAGES) + fi + fi # COMPILE_ENVIRONMENT AC_SUBST(MOZ_DEFAULT_TOOLKIT) @@ -4853,11 +4881,7 @@ AC_SUBST(MOZ_GTK2_LIBS) AC_SUBST(MOC) -if test "$MOZ_ENABLE_GTK2" -then - AC_DEFINE(MOZ_X11) - MOZ_X11=1 -fi +AC_SUBST(MOZ_DFB) AC_SUBST(MOZ_X11) dnl ======================================================== @@ -4972,19 +4996,47 @@ fi AC_DEFINE_UNQUOTED(MOZ_DISTRIBUTION_ID,"$MOZ_DISTRIBUTION_ID") AC_SUBST(MOZ_DISTRIBUTION_ID) + +dnl ======================================================== +dnl complex text support off by default +dnl ======================================================== +MOZ_PANGO=1 +MOZ_ARG_DISABLE_BOOL(pango, +[ --disable-pango Disable usage of Pango ], + MOZ_PANGO=, + MOZ_PANGO=1) + + dnl ======================================================== dnl = Xft and Pango dnl ======================================================== if test "$MOZ_ENABLE_GTK2" then - PKG_CHECK_MODULES(MOZ_XFT, xft) - AC_SUBST(MOZ_XFT_CFLAGS) - AC_SUBST(MOZ_XFT_LIBS) + if test "$MOZ_X11"; then + PKG_CHECK_MODULES(MOZ_XFT, xft) + AC_SUBST(MOZ_XFT_CFLAGS) + AC_SUBST(MOZ_XFT_LIBS) + fi + + AC_SUBST(MOZ_PANGO) PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION) - PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangocairo >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION) - AC_SUBST(MOZ_PANGO_CFLAGS) - AC_SUBST(MOZ_PANGO_LIBS) + + if test "$MOZ_PANGO" + then + PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangocairo >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION) + AC_SUBST(MOZ_PANGO_CFLAGS) + AC_SUBST(MOZ_PANGO_LIBS) + AC_DEFINE(MOZ_PANGO) + else + PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION) + AC_SUBST(MOZ_PANGO_CFLAGS) + AC_SUBST(MOZ_PANGO_LIBS) + + PKG_CHECK_MODULES(FT2, freetype2 > 6.1.0 fontconfig) + AC_SUBST(FT2_CFLAGS) + AC_SUBST(FT2_LIBS) + fi fi dnl ======================================================== diff --git a/gfx/src/thebes/nsSystemFontsGTK2.cpp b/gfx/src/thebes/nsSystemFontsGTK2.cpp index 3474275747e..186d26cfb4a 100644 --- a/gfx/src/thebes/nsSystemFontsGTK2.cpp +++ b/gfx/src/thebes/nsSystemFontsGTK2.cpp @@ -45,18 +45,18 @@ #include #include -#include +#ifdef MOZ_PANGO #include -#include #include +#endif #include #include "nsSystemFontsGTK2.h" #include "gfxPlatformGtk.h" // Glue to avoid build/runtime dependencies on Pango > 1.6 -#ifndef THEBES_USE_PANGO_CAIRO +#if defined(MOZ_PANGO) && !defined(THEBES_USE_PANGO_CAIRO) static gboolean (* PTR_pango_font_description_get_size_is_absolute)(PangoFontDescription*) = nsnull; @@ -101,12 +101,14 @@ static inline void ShutdownPangoLib() { } +#ifdef MOZ_PANGO static inline gboolean MOZ_pango_font_description_get_size_is_absolute(PangoFontDescription *desc) { pango_font_description_get_size_is_absolute(desc); } #endif +#endif nsSystemFontsGTK2::nsSystemFontsGTK2() : mDefaultFontName(NS_LITERAL_STRING("sans-serif")) @@ -190,6 +192,7 @@ nsresult nsSystemFontsGTK2::GetSystemFontInfo(GtkWidget *aWidget, nsString *aFontName, gfxFontStyle *aFontStyle) const { +#ifdef MOZ_PANGO GtkSettings *settings = gtk_widget_get_settings(aWidget); aFontStyle->style = FONT_STYLE_NORMAL; @@ -225,6 +228,18 @@ nsSystemFontsGTK2::GetSystemFontInfo(GtkWidget *aWidget, nsString *aFontName, pango_font_description_free(desc); +#else + /* FIXME: DFB FT2 Hardcoding the system font info for now.. */ + aFontStyle->style = FONT_STYLE_NORMAL; + aFontStyle->systemFont = PR_TRUE; + + NS_NAMED_LITERAL_STRING(fontname, "\"Sans\""); + *aFontName = fontname; + aFontStyle->weight = 400; + aFontStyle->size = 40/3; + +#endif + return NS_OK; } diff --git a/gfx/src/thebes/nsThebesDeviceContext.cpp b/gfx/src/thebes/nsThebesDeviceContext.cpp index 6ac6ab2dd2c..022b03ba3b9 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.cpp +++ b/gfx/src/thebes/nsThebesDeviceContext.cpp @@ -55,11 +55,14 @@ #include #include -#include + #include "nsFont.h" #include +#ifdef MOZ_X11 +#include #include +#endif /* MOZ_X11 */ #include #endif /* GTK2 */ @@ -92,7 +95,7 @@ static nsSystemFontsMac *gSystemFonts = nsnull; #error Need to declare gSystemFonts! #endif -#ifdef MOZ_ENABLE_GTK2 +#if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11) extern "C" { static int x11_error_handler (Display *dpy, XErrorEvent *err) { NS_ASSERTION(PR_FALSE, "X Error"); @@ -271,7 +274,7 @@ nsThebesDeviceContext::Init(nsNativeWidget aWidget) SetDPI(); -#ifdef MOZ_ENABLE_GTK2 +#if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11) if (getenv ("MOZ_X_SYNC")) { PR_LOG (gThebesGFXLog, PR_LOG_DEBUG, ("+++ Enabling XSynchronize\n")); XSynchronize (gdk_x11_get_default_xdisplay(), True); diff --git a/gfx/src/thebes/nsThebesRenderingContext.cpp b/gfx/src/thebes/nsThebesRenderingContext.cpp index c05b3636e86..b977c424dda 100644 --- a/gfx/src/thebes/nsThebesRenderingContext.cpp +++ b/gfx/src/thebes/nsThebesRenderingContext.cpp @@ -974,7 +974,7 @@ nsThebesRenderingContext::GetTextDimensionsInternal(const PRUnichar* aString, return GetWidth(aString, aLength, aDimensions.width, aFontID); } -#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS) || defined(XP_MACOSX) +#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS) || defined(XP_MACOSX) || defined (MOZ_DFB) NS_IMETHODIMP nsThebesRenderingContext::GetTextDimensionsInternal(const char* aString, PRInt32 aLength, diff --git a/gfx/thebes/public/Makefile.in b/gfx/thebes/public/Makefile.in index 6c7cdbfda21..bf9a9e034d4 100644 --- a/gfx/thebes/public/Makefile.in +++ b/gfx/thebes/public/Makefile.in @@ -53,8 +53,22 @@ endif endif ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) -EXPORTS += gfxXlibSurface.h gfxPlatformGtk.h gfxXlibNativeRenderer.h -EXPORTS += gfxPangoFonts.h + +ifdef MOZ_X11 +EXPORTS += gfxXlibSurface.h +endif + +ifdef MOZ_PANGO +EXPORTS += gfxPangoFonts.h +else +EXPORTS += gfxFT2Fonts.h +endif + +ifdef MOZ_DFB +EXPORTS += gfxDirectFBSurface.h +endif + +EXPORTS += gfxPlatformGtk.h gfxGdkNativeRenderer.h EXPORTS += gfxPDFSurface.h gfxPSSurface.h ifdef MOZ_ENABLE_GLITZ diff --git a/gfx/thebes/public/gfxDirectFBSurface.h b/gfx/thebes/public/gfxDirectFBSurface.h new file mode 100644 index 00000000000..82703ecb329 --- /dev/null +++ b/gfx/thebes/public/gfxDirectFBSurface.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is DirectFB Thebes code. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_DIRECTFBSURFACE_H +#define GFX_DIRECTFBSURFACE_H + +#include "gfxASurface.h" + +extern "C" { +#include "direct/messages.h" + +typedef struct _IDirectFB IDirectFB; +typedef struct _IDirectFBSurface IDirectFBSurface; + +} + +class THEBES_API gfxDirectFBSurface : public gfxASurface { +public: + gfxDirectFBSurface(IDirectFB *dfb, IDirectFBSurface *surface); + gfxDirectFBSurface(IDirectFBSurface *surface); + gfxDirectFBSurface(cairo_surface_t *csurf); + + gfxDirectFBSurface(const gfxIntSize& size, gfxImageFormat format); + + virtual ~gfxDirectFBSurface(); + + IDirectFB* DirectFB() { return mDFB; } + IDirectFBSurface* DirectFBSurface() { return mDFBSurface; } + +protected: + IDirectFB *mDFB; + IDirectFBSurface *mDFBSurface; +}; + +#endif /* GFX_DIRECTFBSURFACE_H */ diff --git a/gfx/thebes/public/gfxFT2Fonts.h b/gfx/thebes/public/gfxFT2Fonts.h new file mode 100644 index 00000000000..18a13a6e9c1 --- /dev/null +++ b/gfx/thebes/public/gfxFT2Fonts.h @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Foundation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * Masayuki Nakano + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_GTKDFBFONTS_H +#define GFX_GTKDFBFONTS_H + +#include "cairo.h" +#include "gfxTypes.h" +#include "gfxFont.h" +#include "gfxContext.h" +#include "gfxFontUtils.h" + +typedef struct FT_FaceRec_* FT_Face; + +/** + * FontFamily is a class that describes one of the fonts on the users system. It holds + * each FontEntry (maps more directly to a font face) which holds font type, charset info + * and character map info. + */ +class FontEntry; +class FontFamily +{ +public: + THEBES_INLINE_DECL_REFCOUNTING(FontFamily) + + FontFamily(const nsAString& aName) : + mName(aName) { } + + FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle); + +public: + nsTArray > mFaces; + nsString mName; +}; + +class FontEntry +{ +public: + THEBES_INLINE_DECL_REFCOUNTING(FontEntry) + + FontEntry(const nsString& aFaceName) : + mFontFace(nsnull), mFaceName(aFaceName), mFTFontIndex(0), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE) + { } + + FontEntry(const FontEntry& aFontEntry); + ~FontEntry(); + + const nsString& GetName() const { + return mFaceName; + } + + cairo_font_face_t *CairoFontFace(); + + cairo_font_face_t *mFontFace; + + nsString mFaceName; + nsCString mFilename; + PRUint8 mFTFontIndex; + + PRPackedBool mUnicodeFont : 1; + PRPackedBool mSymbolFont : 1; + PRPackedBool mTrueType : 1; + PRPackedBool mIsType1 : 1; + PRPackedBool mItalic : 1; + PRUint16 mWeight; + + gfxSparseBitSet mCharacterMap; +}; + + + +class gfxFT2Font : public gfxFont { +public: // new functions + gfxFT2Font(FontEntry *aFontEntry, + const gfxFontStyle *aFontStyle); + virtual ~gfxFT2Font (); + + virtual const gfxFont::Metrics& GetMetrics(); + + cairo_font_face_t *CairoFontFace(); + cairo_scaled_font_t *CairoScaledFont(); + + virtual PRBool SetupCairoFont(gfxContext *aContext); + virtual nsString GetUniqueName(); + virtual PRUint32 GetSpaceGlyph(); + + FontEntry *GetFontEntry() { return mFontEntry; } +private: + cairo_scaled_font_t *mScaledFont; + + PRBool mHasSpaceGlyph; + PRUint32 mSpaceGlyph; + PRBool mHasMetrics; + Metrics mMetrics; + gfxFloat mAdjustedSize; + + nsRefPtr mFontEntry; +}; + +class THEBES_API gfxFT2FontGroup : public gfxFontGroup { +public: // new functions + gfxFT2FontGroup (const nsAString& families, + const gfxFontStyle *aStyle); + virtual ~gfxFT2FontGroup (); + + inline gfxFT2Font *GetFontAt (PRInt32 i) { + return static_cast (static_cast (mFonts[i])); + } + +protected: // from gfxFontGroup + virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, + PRUint32 aLength, + const Parameters *aParams, + PRUint32 aFlags); + + virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, + PRUint32 aLength, + const Parameters *aParams, + PRUint32 aFlags); + + virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle); + + +protected: // new functions + void InitTextRun(gfxTextRun *aTextRun); + + void CreateGlyphRunsFT(gfxTextRun *aTextRun); + void AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnichar *str, PRUint32 len); + + static PRBool FontCallback (const nsAString & fontName, + const nsACString & genericName, + void *closure); + PRBool mEnableKerning; + + gfxFT2Font *FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont); + PRUint32 ComputeRanges(); + + struct TextRange { + TextRange(PRUint32 aStart, PRUint32 aEnd) : start(aStart), end(aEnd) { } + PRUint32 Length() const { return end - start; } + nsRefPtr font; + PRUint32 start, end; + }; + + nsTArray mRanges; + nsString mString; +}; + +#endif /* GFX_GTKDFBFONTS_H */ + diff --git a/gfx/thebes/public/gfxPlatformGtk.h b/gfx/thebes/public/gfxPlatformGtk.h index c855c117319..308440d95c7 100644 --- a/gfx/thebes/public/gfxPlatformGtk.h +++ b/gfx/thebes/public/gfxPlatformGtk.h @@ -39,11 +39,20 @@ #ifndef GFX_PLATFORM_GTK_H #define GFX_PLATFORM_GTK_H -#include - #include "gfxPlatform.h" +extern "C" { + typedef struct _GdkDrawable GdkDrawable; +} + class gfxFontconfigUtils; +#ifndef MOZ_PANGO +class FontFamily; +class FontEntry; +typedef struct FT_LibraryRec_ *FT_Library; +#endif + + class THEBES_API gfxPlatformGtk : public gfxPlatform { public: @@ -72,6 +81,11 @@ public: gfxFontGroup *CreateFontGroup(const nsAString &aFamilies, const gfxFontStyle *aStyle); +#ifndef MOZ_PANGO + FontFamily *FindFontFamily(const nsAString& aName); + FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle); +#endif + static PRInt32 DPI() { if (sDPI == -1) { InitDPI(); @@ -80,6 +94,14 @@ public: return sDPI; } +#ifndef MOZ_PANGO + FT_Library GetFTLibrary(); +#endif + + void SetGdkDrawable(gfxASurface *target, + GdkDrawable *drawable); + GdkDrawable *GetGdkDrawable(gfxASurface *target); + protected: static void InitDPI(); diff --git a/gfx/thebes/src/Makefile.in b/gfx/thebes/src/Makefile.in index 04347a57f8e..2feeec2efad 100644 --- a/gfx/thebes/src/Makefile.in +++ b/gfx/thebes/src/Makefile.in @@ -80,15 +80,37 @@ REQUIRES += uconv endif ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) -CPPSRCS += gfxXlibSurface.cpp gfxPlatformGtk.cpp gfxXlibNativeRenderer.cpp -CPPSRCS += gfxPangoFonts.cpp + +ifdef MOZ_PANGO +CPPSRCS += gfxPangoFonts.cpp +else +CPPSRCS += gfxFT2Fonts.cpp +endif + +ifdef MOZ_X11 +CPPSRCS += gfxXlibSurface.cpp +endif + +CPPSRCS += gfxPlatformGtk.cpp gfxGdkNativeRenderer.cpp CPPSRCS += gfxPDFSurface.cpp gfxPSSurface.cpp CPPSRCS += gfxFontconfigUtils.cpp CPPSRCS += nsUnicodeRange.cpp + +ifdef MOZ_X11 CSRCS = cairo-xlib-utils.c +endif + +ifdef MOZ_DFB +CSRCS = cairo-gdk-utils.c +endif + EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) $(ZLIB_LIBS) $(MOZ_XFT_LIBS) $(XLDFLAGS) $(XLIBS) endif +ifdef MOZ_DFB +CPPSRCS += gfxDirectFBSurface.cpp +endif + ifeq ($(MOZ_WIDGET_TOOLKIT),beos) CPPSRCS += gfxBeOSSurface.cpp gfxBeOSPlatform.cpp CPPSRCS += gfxPangoFonts.cpp diff --git a/gfx/thebes/src/gfxASurface.cpp b/gfx/thebes/src/gfxASurface.cpp index 27a23166f24..3af02d2e0bb 100644 --- a/gfx/thebes/src/gfxASurface.cpp +++ b/gfx/thebes/src/gfxASurface.cpp @@ -55,6 +55,10 @@ #include "gfxQuartzImageSurface.h" #endif +#ifdef CAIRO_HAS_DIRECTFB_SURFACE +#include "gfxDirectFBSurface.h" +#endif + #include #include @@ -162,6 +166,11 @@ gfxASurface::Wrap (cairo_surface_t *csurf) else if (stype == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) { result = new gfxQuartzImageSurface(csurf); } +#endif +#ifdef CAIRO_HAS_DIRECTFB_SURFACE + else if (stype == CAIRO_SURFACE_TYPE_DIRECTFB) { + result = new gfxDirectFBSurface(csurf); + } #endif else { result = new gfxUnknownSurface(csurf); diff --git a/gfx/thebes/src/gfxDirectFBSurface.cpp b/gfx/thebes/src/gfxDirectFBSurface.cpp new file mode 100644 index 00000000000..62a87c6efdd --- /dev/null +++ b/gfx/thebes/src/gfxDirectFBSurface.cpp @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "gfxDirectFBSurface.h" + +#include "cairo-directfb.h" + +gfxDirectFBSurface::gfxDirectFBSurface(IDirectFB *dfb, IDirectFBSurface *dfbs) + : mDFB(nsnull), mDFBSurface(nsnull) +{ + dfb->AddRef( dfb ); + dfbs->AddRef( dfbs ); + + cairo_surface_t *surf = cairo_directfb_surface_create(dfb, dfbs); + + mDFB = dfb; + mDFBSurface = dfbs; + + Init(surf); +} + +gfxDirectFBSurface::gfxDirectFBSurface(IDirectFBSurface *dfbs) + : mDFB(nsnull), mDFBSurface(nsnull) +{ + DFBResult ret; + + dfbs->AddRef( dfbs ); + + /* Lightweight, getting singleton */ + ret = DirectFBCreate( &mDFB ); + if (ret) { + D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: DirectFBCreate() failed!\n" ); + return; + } + + cairo_surface_t *surf = cairo_directfb_surface_create(mDFB, dfbs); + + mDFBSurface = dfbs; + + Init(surf); +} + +gfxDirectFBSurface::gfxDirectFBSurface(cairo_surface_t *csurf) +{ + mDFB = nsnull; + mDFBSurface = nsnull; + + Init(csurf, PR_TRUE); +} + +gfxDirectFBSurface::gfxDirectFBSurface(const gfxIntSize& size, gfxImageFormat format) : + mDFB(nsnull), mDFBSurface(nsnull) +{ + DFBResult ret; + DFBSurfaceDescription desc; + + if (!CheckSurfaceSize(size) || size.width <= 0 || size.height <= 0) + return; + + /* Lightweight, getting singleton */ + ret = DirectFBCreate( &mDFB ); + if (ret) { + D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: DirectFBCreate() failed!\n" ); + return; + } + + desc.flags = (DFBSurfaceDescriptionFlags)( DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT ); + desc.width = size.width; + desc.height = size.height; + + switch (format) { + case gfxASurface::ImageFormatARGB32: + desc.pixelformat = DSPF_ARGB; + break; + + case gfxASurface::ImageFormatRGB24: + desc.pixelformat = DSPF_RGB32; + break; + + case gfxASurface::ImageFormatA8: + desc.pixelformat = DSPF_A8; + break; + + case gfxASurface::ImageFormatA1: + desc.pixelformat = DSPF_A1; + break; + + default: + D_BUG( "unknown format" ); + return; + } + + ret = mDFB->CreateSurface( mDFB, &desc, &mDFBSurface ); + if (ret) { + D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: " + "IDirectFB::CreateSurface( %dx%d ) failed!\n", desc.width, desc.height ); + return; + } + + cairo_surface_t *surface = cairo_directfb_surface_create(mDFB, mDFBSurface); + + Init(surface); +} + +gfxDirectFBSurface::~gfxDirectFBSurface() +{ + if (mDFBSurface) + mDFBSurface->Release( mDFBSurface ); + + if (mDFB) + mDFB->Release( mDFB ); +} + diff --git a/gfx/thebes/src/gfxFT2Fonts.cpp b/gfx/thebes/src/gfxFT2Fonts.cpp new file mode 100644 index 00000000000..e7010c5b0cc --- /dev/null +++ b/gfx/thebes/src/gfxFT2Fonts.cpp @@ -0,0 +1,862 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Foundation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "gfxPlatformGtk.h" +#include "gfxTypes.h" +#include "gfxFT2Fonts.h" +#include +#include "cairo-ft.h" +#include +#include "gfxFontUtils.h" + +/** + * FontEntry + */ + +FontEntry::FontEntry(const FontEntry& aFontEntry) : + mFaceName(aFontEntry.mFaceName), + mUnicodeFont(aFontEntry.mUnicodeFont), + mSymbolFont(aFontEntry.mSymbolFont), + mItalic(aFontEntry.mItalic), + mWeight(aFontEntry.mWeight), + mCharacterMap(aFontEntry.mCharacterMap) +{ + if (aFontEntry.mFontFace) + mFontFace = cairo_font_face_reference(aFontEntry.mFontFace); + else + mFontFace = nsnull; +} + +FontEntry::~FontEntry() +{ + if (mFontFace) { + cairo_font_face_destroy(mFontFace); + mFontFace = nsnull; + } +} + +static void +FTFontDestroyFunc(void *data) +{ + FT_Face face = (FT_Face)data; + FT_Done_Face(face); +} + +cairo_font_face_t * +FontEntry::CairoFontFace() +{ + static cairo_user_data_key_t key; + + if (!mFontFace) { + FT_Face face; + FT_New_Face(gfxPlatformGtk::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face); + mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0); + cairo_font_face_set_user_data(mFontFace, &key, face, FTFontDestroyFunc); + } + return mFontFace; +} + +FontEntry * +FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle) +{ + PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0; + + FontEntry *weightList[10] = { 0 }; + for (PRUint32 j = 0; j < 2; j++) { + PRBool matchesSomething = PR_FALSE; + // build up an array of weights that match the italicness we're looking for + for (PRUint32 i = 0; i < mFaces.Length(); i++) { + FontEntry *fe = mFaces[i]; + const PRUint8 weight = (fe->mWeight / 100); + if (fe->mItalic == italic) { + weightList[weight] = fe; + matchesSomething = PR_TRUE; + } + } + if (matchesSomething) + break; + italic = !italic; + } + + PRInt8 baseWeight, weightDistance; + aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance); + + // 500 isn't quite bold so we want to treat it as 400 if we don't + // have a 500 weight + if (baseWeight == 5 && weightDistance == 0) { + // If we have a 500 weight then use it + if (weightList[5]) + return weightList[5]; + + // Otherwise treat as 400 + baseWeight = 4; + } + + PRInt8 matchBaseWeight = 0; + PRInt8 direction = (baseWeight > 5) ? 1 : -1; + for (PRInt8 i = baseWeight; ; i += direction) { + if (weightList[i]) { + matchBaseWeight = i; + break; + } + + // if we've reached one side without finding a font, + // go the other direction until we find a match + if (i == 1 || i == 9) + direction = -direction; + } + + FontEntry *matchFE; + const PRInt8 absDistance = abs(weightDistance); + direction = (weightDistance >= 0) ? 1 : -1; + for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) { + if (weightList[i]) { + matchFE = weightList[i]; + k++; + } + if (k > absDistance) + break; + } + + if (!matchFE) + matchFE = weightList[matchBaseWeight]; + + NS_ASSERTION(matchFE, "we should always be able to return something here"); + return matchFE; +} + + + +/** + * gfxFT2FontGroup + */ + +PRBool +gfxFT2FontGroup::FontCallback(const nsAString& fontName, + const nsACString& genericName, + void *closure) +{ + nsStringArray *sa = static_cast(closure); + + if (!fontName.IsEmpty() && sa->IndexOf(fontName) < 0) { + sa->AppendString(fontName); +#ifdef DEBUG_pavlov + printf(" - %s\n", NS_ConvertUTF16toUTF8(fontName).get()); +#endif + } + + return PR_TRUE; +} + +/** + * Look up the font in the gfxFont cache. If we don't find it, create one. + * In either case, add a ref, append it to the aFonts array, and return it --- + * except for OOM in which case we do nothing and return null. + */ +static already_AddRefed +GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle) +{ + nsRefPtr font = gfxFontCache::GetCache()->Lookup(aName, aStyle); + if (!font) { + FontEntry *fe = gfxPlatformGtk::GetPlatform()->FindFontEntry(aName, *aStyle); + if (!fe) { + printf("Failed to find font entry for %s\n", NS_ConvertUTF16toUTF8(aName).get()); + return nsnull; + } + + font = new gfxFT2Font(fe, aStyle); + if (!font) + return nsnull; + gfxFontCache::GetCache()->AddNew(font); + } + gfxFont *f = nsnull; + font.swap(f); + return static_cast(f); +} + + +gfxFT2FontGroup::gfxFT2FontGroup(const nsAString& families, + const gfxFontStyle *aStyle) + : gfxFontGroup(families, aStyle) +{ +#ifdef DEBUG_pavlov + printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get()); +#endif + nsStringArray familyArray; + ForEachFont(FontCallback, &familyArray); + + if (familyArray.Count() == 0) { + nsAutoString prefFamilies; + gfxPlatformGtk::GetPlatform()->GetPrefFonts(aStyle->langGroup.get(), prefFamilies, nsnull); + if (!prefFamilies.IsEmpty()) { + ForEachFont(prefFamilies, aStyle->langGroup, FontCallback, &familyArray); + } + } +#if 0 /* FIXME DFB */ + if (familyArray.Count() == 0) { + printf("failde to find a font. sadface\n"); + // We want to get rid of this entirely at some point, but first we need real lists of fonts. + QFont defaultFont; + QFontInfo fi (defaultFont); + familyArray.AppendString(nsDependentString(static_cast(fi.family().utf16()))); + } +#endif + + for (int i = 0; i < familyArray.Count(); i++) { + nsRefPtr font = GetOrMakeFont(*familyArray[i], &mStyle); + if (font) { + mFonts.AppendElement(font); + } + } +} + +gfxFT2FontGroup::~gfxFT2FontGroup() +{ +} + +gfxFontGroup * +gfxFT2FontGroup::Copy(const gfxFontStyle *aStyle) +{ + return new gfxFT2FontGroup(mFamilies, aStyle); +} + +/** + * We use this to append an LTR or RTL Override character to the start of the + * string. This forces Pango to honour our direction even if there are neutral + * characters in the string. + */ +static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString) +{ + static const PRUnichar overrides[2][2] = { { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO + AppendUTF16toUTF8(overrides[aIsRTL], aString); + return 3; // both overrides map to 3 bytes in UTF8 +} + +gfxTextRun *gfxFT2FontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLength, + const Parameters* aParams, PRUint32 aFlags) +{ + gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags); + if (!textRun) + return nsnull; + + textRun->RecordSurrogates(aString); + + mString.Assign(nsDependentSubstring(aString, aString + aLength)); + + InitTextRun(textRun); + + textRun->FetchGlyphExtents(aParams->mContext); + + return textRun; +} + +gfxTextRun *gfxFT2FontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength, + const Parameters *aParams, PRUint32 aFlags) +{ + NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set"); + gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags); + if (!textRun) + return nsnull; + + const char *chars = reinterpret_cast(aString); + + mString.Assign(NS_ConvertASCIItoUTF16(nsDependentCSubstring(chars, chars + aLength))); + + InitTextRun(textRun); + + textRun->FetchGlyphExtents(aParams->mContext); + + return textRun; +} + +void gfxFT2FontGroup::InitTextRun(gfxTextRun *aTextRun) +{ + CreateGlyphRunsFT(aTextRun); +} + + +// Helper function to return the leading UTF-8 character in a char pointer +// as 32bit number. Also sets the length of the current character (i.e. the +// offset to the next one) in the second argument +PRUint32 getUTF8CharAndNext(const PRUint8 *aString, PRUint8 *aLength) +{ + *aLength = 1; + if (aString[0] < 0x80) { // normal 7bit ASCII char + return aString[0]; + } + if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes + *aLength = 2; + return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F); + } + if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes + *aLength = 3; + return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) + + (aString[2] & 0x3F); + } + if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes + *aLength = 4; + return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) + + ((aString[2] & 0x3F) << 6) + (aString[3] & 0x3F); + } + return aString[0]; +} + + + + + + + + +PRBool +HasCharacter(gfxFT2Font *aFont, PRUint32 ch) +{ + if (aFont->GetFontEntry()->mCharacterMap.test(ch)) + return PR_TRUE; + + // XXX move this lock way way out + FT_Face face = cairo_ft_scaled_font_lock_face(aFont->CairoScaledFont()); + FT_UInt gid = FT_Get_Char_Index(face, ch); + cairo_ft_scaled_font_unlock_face(aFont->CairoScaledFont()); + + if (gid != 0) { + aFont->GetFontEntry()->mCharacterMap.set(ch); + return PR_TRUE; + } + return PR_FALSE; +} + +#if 0 +inline FontEntry * +gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<>& foo, PRUint32 ch) +{ + for (int i = 0; i < aGroup->FontListLength(); i++) { + nsRefPtr font = aGroup->GetFontAt(i); + if (HasCharacter(font, ch)) + return font; + } + return nsnull; +} +#endif + +inline gfxFT2Font * +gfxFT2FontGroup::FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont) +{ + gfxFT2Font *selectedFont; + + // if this character or the next one is a joiner use the + // same font as the previous range if we can + if (gfxFontUtils::IsJoiner(ch) || gfxFontUtils::IsJoiner(prevCh) || gfxFontUtils::IsJoiner(nextCh)) { + if (aFont && HasCharacter(aFont, ch)) + return aFont; + } + + for (PRUint32 i = 0; i < FontListLength(); i++) { + nsRefPtr font = GetFontAt(i); + if (HasCharacter(font, ch)) + return font; + } + return nsnull; + +#if 0 + // check the list of fonts + selectedFont = WhichFontSupportsChar(mGroup->GetFontList(), ch); + + + // don't look in other fonts if the character is in a Private Use Area + if ((ch >= 0xE000 && ch <= 0xF8FF) || + (ch >= 0xF0000 && ch <= 0x10FFFD)) + return selectedFont; + + // check out the style's language group + if (!selectedFont) { + nsAutoTArray, 5> fonts; + this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts); + selectedFont = WhichFontSupportsChar(fonts, ch); + } + + // otherwise search prefs + if (!selectedFont) { + /* first check with the script properties to see what they think */ + if (ch <= 0xFFFF) { + PRUint32 unicodeRange = FindCharUnicodeRange(ch); + + /* special case CJK */ + if (unicodeRange == kRangeSetCJK) { + if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) + PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK")); + + nsAutoTArray, 15> fonts; + this->GetCJKPrefFonts(fonts); + selectedFont = WhichFontSupportsChar(fonts, ch); + } else { + const char *langGroup = LangGroupFromUnicodeRange(unicodeRange); + if (langGroup) { + PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup)); + + nsAutoTArray, 5> fonts; + this->GetPrefFonts(langGroup, fonts); + selectedFont = WhichFontSupportsChar(fonts, ch); + } + } + } + } + + // before searching for something else check the font used for the previous character + if (!selectedFont && aFont && HasCharacter(aFont, ch)) + selectedFont = aFont; + + // otherwise look for other stuff + if (!selectedFont) { + PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Looking for best match")); + + nsRefPtr refFont = mGroup->GetFontAt(0); + gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform(); + selectedFont = platform->FindFontForChar(ch, refFont); + } + + return selectedFont; +#endif +} + +PRUint32 +gfxFT2FontGroup::ComputeRanges() +{ + const PRUnichar *str = mString.get(); + PRUint32 len = mString.Length(); + + mRanges.Clear(); + + PRUint32 prevCh = 0; + for (PRUint32 i = 0; i < len; i++) { + const PRUint32 origI = i; // save off incase we increase for surrogate + PRUint32 ch = str[i]; + if ((i+1 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+1])) { + i++; + ch = SURROGATE_TO_UCS4(ch, str[i]); + } + + PRUint32 nextCh = 0; + if (i+1 < len) { + nextCh = str[i+1]; + if ((i+2 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+2])) + nextCh = SURROGATE_TO_UCS4(nextCh, str[i+2]); + } + gfxFT2Font *fe = FindFontForChar(ch, + prevCh, + nextCh, + (mRanges.Length() == 0) ? nsnull : mRanges[mRanges.Length() - 1].font); + + prevCh = ch; + + if (mRanges.Length() == 0) { + TextRange r(0,1); + r.font = fe; + mRanges.AppendElement(r); + } else { + TextRange& prevRange = mRanges[mRanges.Length() - 1]; + if (prevRange.font != fe) { + // close out the previous range + prevRange.end = origI; + + TextRange r(origI, i+1); + r.font = fe; + mRanges.AppendElement(r); + } + } + } + mRanges[mRanges.Length()-1].end = len; + + PRUint32 nranges = mRanges.Length(); + return nranges; +} + +void gfxFT2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun) +{ + ComputeRanges(); + + const PRUnichar *strStart = mString.get(); + for (PRUint32 i = 0; i < mRanges.Length(); ++i) { + const TextRange& range = mRanges[i]; + const PRUnichar *rangeString = strStart + range.start; + PRUint32 rangeLength = range.Length(); + + gfxFT2Font *font = range.font ? range.font.get() : GetFontAt(0); + AddRange(aTextRun, font, rangeString, rangeLength); + } + +} + +void +gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnichar *str, PRUint32 len) +{ + const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit(); + // we'll pass this in/figure it out dynamically, but at this point there can be only one face. + FT_Face face = cairo_ft_scaled_font_lock_face(font->CairoScaledFont()); + + gfxTextRun::CompressedGlyph g; + + aTextRun->AddGlyphRun(font, 0); + for (PRUint32 i = 0; i < len; i++) { + PRUint32 ch = str[i]; + + if (ch == 0) { + // treat this null byte as a missing glyph, don't create a glyph for it + aTextRun->SetMissingGlyph(i, 0); + continue; + } + + NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected"); + FT_UInt gid = FT_Get_Char_Index(face, ch); // find the glyph id + PRInt32 advance = 0; + + if (gid == font->GetSpaceGlyph()) { + advance = (int)(font->GetMetrics().spaceWidth * appUnitsPerDevUnit); + } else if (gid == 0) { + advance = -1; // trigger the missing glyphs case below + } else { + // find next character and its glyph -- in case they exist + // and exist in the current font face -- to compute kerning + PRUint32 chNext = 0; + FT_UInt gidNext = 0; + FT_Pos lsbDeltaNext = 0; + + if (FT_HAS_KERNING(face) && i + 1 < len) { + chNext = str[i+1]; + if (chNext != 0) { + gidNext = FT_Get_Char_Index(face, chNext); + if (gidNext && gidNext != font->GetSpaceGlyph()) { + FT_Load_Glyph(face, gidNext, FT_LOAD_DEFAULT); + lsbDeltaNext = face->glyph->lsb_delta; + } + } + } + + // now load the current glyph + FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load glyph into the slot + advance = face->glyph->advance.x; + + // now add kerning to the current glyph's advance + if (chNext && gidNext) { + FT_Vector kerning; kerning.x = 0; + FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning); + advance += kerning.x; + if (face->glyph->rsb_delta - lsbDeltaNext >= 32) { + advance -= 64; + } else if (face->glyph->rsb_delta - lsbDeltaNext < -32) { + advance += 64; + } + } + + // now apply unit conversion and scaling + advance = (advance >> 6) * appUnitsPerDevUnit; + } +#ifdef DEBUG_thebes_2 + printf(" gid=%d, advance=%d (%s)\n", gid, advance, + NS_LossyConvertUTF16toASCII(font->GetName()).get()); +#endif + + if (advance >= 0 && + gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) && + gfxTextRun::CompressedGlyph::IsSimpleGlyphID(gid)) { + aTextRun->SetSimpleGlyph(i, g.SetSimpleGlyph(advance, gid)); + } else if (gid == 0) { + // gid = 0 only happens when the glyph is missing from the font + aTextRun->SetMissingGlyph(i, ch); + } else { + gfxTextRun::DetailedGlyph details; + details.mGlyphID = gid; + NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!"); + details.mAdvance = advance; + details.mXOffset = 0; + details.mYOffset = 0; + g.SetComplex(aTextRun->IsClusterStart(i), PR_TRUE, 1); + aTextRun->SetGlyphs(i, g, &details); + } + } + + cairo_ft_scaled_font_unlock_face(font->CairoScaledFont()); +} + +/** + * gfxFT2Font + */ +gfxFT2Font::gfxFT2Font(FontEntry *aFontEntry, + const gfxFontStyle *aFontStyle) + : gfxFont(aFontEntry->GetName(), aFontStyle), + mScaledFont(nsnull), + mHasSpaceGlyph(PR_FALSE), + mSpaceGlyph(0), + mHasMetrics(PR_FALSE), + mAdjustedSize(0), + mFontEntry(aFontEntry) +{ +} + +gfxFT2Font::~gfxFT2Font() +{ + if (mScaledFont) { + cairo_scaled_font_destroy(mScaledFont); + mScaledFont = nsnull; + } +} + +// rounding and truncation functions for a Freetype floating point number +// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer +// part and low 6 bits for the fractional part. +#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1 +#define MOZ_FT_TRUNC(x) ((x) >> 6) +#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \ + MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s)))) + +const gfxFont::Metrics& +gfxFT2Font::GetMetrics() +{ + if (mHasMetrics) + return mMetrics; + + mMetrics.emHeight = GetStyle()->size; + + FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont()); + + if (!face) { + // Abort here already, otherwise we crash in the following + // this can happen if the font-size requested is zero. + // The metrics will be incomplete, but then we don't care. + return mMetrics; + } + + mMetrics.emHeight = GetStyle()->size; + + FT_UInt gid; // glyph ID + + const double emUnit = 1.0 * face->units_per_EM; + const double xScale = face->size->metrics.x_ppem / emUnit; + const double yScale = face->size->metrics.y_ppem / emUnit; + + // properties of space + gid = FT_Get_Char_Index(face, ' '); + if (gid) { + FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); + // face->glyph->metrics.width doesn't work for spaces, use advance.x instead + mMetrics.spaceWidth = face->glyph->advance.x >> 6; + // save the space glyph + mSpaceGlyph = gid; + } else { + NS_ASSERTION(0, "blah"); + } + + // properties of 'x', also use its width as average width + gid = FT_Get_Char_Index(face, 'x'); // select the glyph + if (gid) { + // Load glyph into glyph slot. Here, use no_scale to get font units. + FT_Load_Glyph(face, gid, FT_LOAD_NO_SCALE); + mMetrics.xHeight = face->glyph->metrics.height * yScale; + mMetrics.aveCharWidth = face->glyph->metrics.width * xScale; + } else { + // this font doesn't have an 'x'... + // fake these metrics using a fraction of the font size + mMetrics.xHeight = mMetrics.emHeight * 0.5; + mMetrics.aveCharWidth = mMetrics.emHeight * 0.5; + } + + // compute an adjusted size if we need to + if (mAdjustedSize == 0 && GetStyle()->sizeAdjust != 0) { + gfxFloat aspect = mMetrics.xHeight / GetStyle()->size; + mAdjustedSize = GetStyle()->GetAdjustedSize(aspect); + mMetrics.emHeight = mAdjustedSize; + } + + // now load the OS/2 TrueType table to load access some more properties + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2 && os2->version != 0xFFFF) { // should be there if not old Mac font + // if we are here we can improve the avgCharWidth + mMetrics.aveCharWidth = os2->xAvgCharWidth * xScale; + + mMetrics.superscriptOffset = os2->ySuperscriptYOffset * yScale; + mMetrics.superscriptOffset = PR_MAX(1, mMetrics.superscriptOffset); + // some fonts have the incorrect sign (from gfxPangoFonts) + mMetrics.subscriptOffset = fabs(os2->ySubscriptYOffset * yScale); + mMetrics.subscriptOffset = PR_MAX(1, fabs(mMetrics.subscriptOffset)); + mMetrics.strikeoutOffset = os2->yStrikeoutPosition * yScale; + mMetrics.strikeoutSize = os2->yStrikeoutSize * yScale; + } else { + // use fractions of emHeight instead of xHeight for these to be more robust + mMetrics.superscriptOffset = mMetrics.emHeight * 0.5; + mMetrics.subscriptOffset = mMetrics.emHeight * 0.2; + mMetrics.strikeoutOffset = mMetrics.emHeight * 0.3; + mMetrics.strikeoutSize = face->underline_thickness * yScale; + } + // seems that underlineOffset really has to be negative + mMetrics.underlineOffset = face->underline_position * yScale; + mMetrics.underlineSize = face->underline_thickness * yScale; + + // descents are negative in FT but Thebes wants them positive + mMetrics.emAscent = face->ascender * yScale; + mMetrics.emDescent = -face->descender * yScale; + mMetrics.maxHeight = face->height * yScale; + mMetrics.maxAscent = face->bbox.yMax * yScale; + mMetrics.maxDescent = -face->bbox.yMin * yScale; + mMetrics.maxAdvance = face->max_advance_width * xScale; + // leading are not available directly (only for WinFNTs) + double lineHeight = mMetrics.maxAscent + mMetrics.maxDescent; + if (lineHeight > mMetrics.emHeight) { + mMetrics.internalLeading = lineHeight - mMetrics.emHeight; + } else { + mMetrics.internalLeading = 0; + } + mMetrics.externalLeading = 0; // normal value for OS/2 fonts, too + + SanitizeMetrics(&mMetrics, PR_FALSE); + + /* + printf("gfxOS2Font[%#x]::GetMetrics():\n" + " emHeight=%f == %f=gfxFont::style.size == %f=adjSz\n" + " maxHeight=%f xHeight=%f\n" + " aveCharWidth=%f==xWidth spaceWidth=%f\n" + " supOff=%f SubOff=%f strOff=%f strSz=%f\n" + " undOff=%f undSz=%f intLead=%f extLead=%f\n" + " emAsc=%f emDesc=%f maxH=%f\n" + " maxAsc=%f maxDes=%f maxAdv=%f\n", + (unsigned)this, + mMetrics.emHeight, GetStyle()->size, mAdjustedSize, + mMetrics.maxHeight, mMetrics.xHeight, + mMetrics.aveCharWidth, mMetrics.spaceWidth, + mMetrics.superscriptOffset, mMetrics.subscriptOffset, + mMetrics.strikeoutOffset, mMetrics.strikeoutSize, + mMetrics.underlineOffset, mMetrics.underlineSize, + mMetrics.internalLeading, mMetrics.externalLeading, + mMetrics.emAscent, mMetrics.emDescent, mMetrics.maxHeight, + mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance + ); + */ + + // XXX mMetrics.height needs to be set. + cairo_ft_scaled_font_unlock_face(CairoScaledFont()); + + mHasMetrics = PR_TRUE; + return mMetrics; +} + + +nsString +gfxFT2Font::GetUniqueName() +{ + return mName; +} + +PRUint32 +gfxFT2Font::GetSpaceGlyph() +{ + NS_ASSERTION (GetStyle ()->size != 0, + "forgot to short-circuit a text run with zero-sized font?"); + + if(!mHasSpaceGlyph) + { + FT_UInt gid = 0; // glyph ID + FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont()); + gid = FT_Get_Char_Index(face, ' '); + FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); + mSpaceGlyph = gid; + mHasSpaceGlyph = PR_TRUE; + cairo_ft_scaled_font_unlock_face(CairoScaledFont()); + } + return mSpaceGlyph; +} + +cairo_font_face_t * +gfxFT2Font::CairoFontFace() +{ + // XXX we need to handle fake bold here (or by having a sepaerate font entry) + if (mStyle.weight >= 600 && mFontEntry->mWeight < 600) + printf("** We want fake weight\n"); + return mFontEntry->CairoFontFace(); +} + +cairo_scaled_font_t * +gfxFT2Font::CairoScaledFont() +{ + if (!mScaledFont) { + cairo_matrix_t sizeMatrix; + cairo_matrix_t identityMatrix; + + // XXX deal with adjusted size + cairo_matrix_init_scale(&sizeMatrix, mStyle.size, mStyle.size); + cairo_matrix_init_identity(&identityMatrix); + + // synthetic oblique by skewing via the font matrix + PRBool needsOblique = (!mFontEntry->mItalic && (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE))); + + if (needsOblique) { + const double kSkewFactor = 0.25; + + cairo_matrix_t style; + cairo_matrix_init(&style, + 1, //xx + 0, //yx + -1 * kSkewFactor, //xy + 1, //yy + 0, //x0 + 0); //y0 + cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style); + } + + cairo_font_options_t *fontOptions = cairo_font_options_create(); + mScaledFont = cairo_scaled_font_create(CairoFontFace(), &sizeMatrix, + &identityMatrix, fontOptions); + cairo_font_options_destroy(fontOptions); + } + + NS_ASSERTION(mAdjustedSize == 0.0 || + cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS, + "Failed to make scaled font"); + + return mScaledFont; +} + +PRBool +gfxFT2Font::SetupCairoFont(gfxContext *aContext) +{ + cairo_scaled_font_t *scaledFont = CairoScaledFont(); + + if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) { + // Don't cairo_set_scaled_font as that would propagate the error to + // the cairo_t, precluding any further drawing. + return PR_FALSE; + } + cairo_set_scaled_font(aContext->GetCairo(), scaledFont); + return PR_TRUE; +} diff --git a/gfx/thebes/src/gfxPlatformGtk.cpp b/gfx/thebes/src/gfxPlatformGtk.cpp index 42480ad9821..22a5accd87c 100644 --- a/gfx/thebes/src/gfxPlatformGtk.cpp +++ b/gfx/thebes/src/gfxPlatformGtk.cpp @@ -36,40 +36,70 @@ * * ***** END LICENSE BLOCK ***** */ +#ifdef MOZ_PANGO #define PANGO_ENABLE_BACKEND #define PANGO_ENABLE_ENGINE +#endif #include "gfxPlatformGtk.h" #include "gfxFontconfigUtils.h" +#ifdef MOZ_PANGO +#include #include "gfxPangoFonts.h" #include "gfxContext.h" +#else +#include +#include FT_FREETYPE_H +#include "gfxFT2Fonts.h" +#endif #include "cairo.h" #include -#include #include "gfxImageSurface.h" +#ifdef MOZ_X11 +#include #include "gfxXlibSurface.h" +#endif /* MOZ_X11 */ -#include "gfxPangoFonts.h" - -#include +#ifdef MOZ_DFB +#include "gfxDirectFBSurface.h" +#endif #ifdef MOZ_ENABLE_GLITZ #include "gfxGlitzSurface.h" #include "glitz-glx.h" #endif +#ifdef MOZ_DFB +#include "gfxDirectFBSurface.h" +#endif + #include #include "nsMathUtils.h" #include "lcms.h" +#ifndef MOZ_PANGO +#include +#include FT_FREETYPE_H +#endif + PRInt32 gfxPlatformGtk::sDPI = -1; gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull; +static cairo_user_data_key_t cairo_gdk_drawable_key; + +#ifndef MOZ_PANGO +typedef nsDataHashtable > FontTable; +static FontTable *gPlatformFonts = NULL; +static FontTable *gPlatformFontAliases = NULL; +static FT_Library gPlatformFTLibrary = NULL; +#endif + + static cairo_user_data_key_t cairo_gdk_pixmap_key; static void do_gdk_pixmap_unref (void *data) { @@ -86,6 +116,20 @@ gfxPlatformGtk::gfxPlatformGtk() if (!sFontconfigUtils) sFontconfigUtils = gfxFontconfigUtils::GetFontconfigUtils(); +#ifndef MOZ_PANGO + FT_Init_FreeType(&gPlatformFTLibrary); + + gPlatformFonts = new FontTable(); + /* FIXME: DFB */ + //gPlatformFonts->Init(100); + gPlatformFonts->Init(20); + gPlatformFontAliases = new FontTable(); + /* FIXME: DFB */ + //gPlatformFontAliases->Init(100); + gPlatformFontAliases->Init(20); + UpdateFontList(); +#endif + InitDPI(); } @@ -94,7 +138,17 @@ gfxPlatformGtk::~gfxPlatformGtk() gfxFontconfigUtils::Shutdown(); sFontconfigUtils = nsnull; +#ifdef MOZ_PANGO gfxPangoFont::Shutdown(); +#else + delete gPlatformFonts; + gPlatformFonts = NULL; + delete gPlatformFontAliases; + gPlatformFontAliases = NULL; + + FT_Done_FreeType(gPlatformFTLibrary); + gPlatformFTLibrary = NULL; +#endif #if 0 // It would be nice to do this (although it might need to be after @@ -111,6 +165,7 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size, { nsRefPtr newSurface = nsnull; +#ifdef MOZ_X11 int glitzf; int xrenderFormatID; switch (imageFormat) { @@ -164,6 +219,7 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size, newSurface->SetData(&cairo_gdk_pixmap_key, pixmap, do_gdk_pixmap_unref); + SetGdkDrawable(newSurface, GDK_DRAWABLE(pixmap)); } else { // something went wrong with the surface creation. // Ignore and let's fall back to image surfaces. @@ -207,6 +263,7 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size, newSurface = new gfxGlitzSurface(gdraw, gsurf, PR_TRUE); #endif } +#endif if (newSurface) { gfxContext tmpCtx(newSurface); @@ -217,6 +274,8 @@ gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size, return newSurface.forget(); } +#ifdef MOZ_PANGO + nsresult gfxPlatformGtk::GetFontList(const nsACString& aLangGroup, const nsACString& aGenericFamily, @@ -255,13 +314,236 @@ gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies, return new gfxPangoFontGroup(aFamilies, aStyle); } +#else + +nsresult +gfxPlatformGtk::GetFontList(const nsACString& aLangGroup, + const nsACString& aGenericFamily, + nsStringArray& aListOfFonts) +{ + return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily, + aListOfFonts); +} + +nsresult +gfxPlatformGtk::UpdateFontList() +{ + FcPattern *pat = NULL; + FcObjectSet *os = NULL; + FcFontSet *fs = NULL; + PRInt32 result = -1; + + pat = FcPatternCreate(); + os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_WEIGHT, FC_SLANT, FC_WIDTH, NULL); + + fs = FcFontList(NULL, pat, os); + + + for (int i = 0; i < fs->nfont; i++) { + char *str; + + if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch) + continue; + + //printf("Family: %s\n", str); + + nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get()); + nsAutoString key(name); + /* FIXME DFB */ + //ToLowerCase(key); + nsRefPtr ff; + if (!gPlatformFonts->Get(key, &ff)) { + ff = new FontFamily(name); + gPlatformFonts->Put(key, ff); + } + + nsRefPtr fe = new FontEntry(ff->mName); + ff->mFaces.AppendElement(fe); + + if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) { + fe->mFilename = nsDependentCString(str); + //printf(" - file: %s\n", str); + } + + int x; + if (FcPatternGetInteger(fs->fonts[i], FC_INDEX, 0, &x) == FcResultMatch) { + //printf(" - index: %d\n", x); + fe->mFTFontIndex = x; + } else { + fe->mFTFontIndex = 0; + } + + if (FcPatternGetInteger(fs->fonts[i], FC_WEIGHT, 0, &x) == FcResultMatch) { + switch(x) { + case 0: + fe->mWeight = 100; + break; + case 40: + fe->mWeight = 200; + break; + case 50: + fe->mWeight = 300; + break; + case 75: + case 80: + fe->mWeight = 400; + break; + case 100: + fe->mWeight = 500; + break; + case 180: + fe->mWeight = 600; + break; + case 200: + fe->mWeight = 700; + break; + case 205: + fe->mWeight = 800; + break; + case 210: + fe->mWeight = 900; + break; + default: + // rough estimate + fe->mWeight = (((x * 4) + 100) / 100) * 100; + break; + } + //printf(" - weight: %d\n", fe->mWeight); + } + + fe->mItalic = PR_FALSE; + if (FcPatternGetInteger(fs->fonts[i], FC_SLANT, 0, &x) == FcResultMatch) { + switch (x) { + case FC_SLANT_ITALIC: + case FC_SLANT_OBLIQUE: + fe->mItalic = PR_TRUE; + } + //printf(" - slant: %d\n", x); + } + + //if (FcPatternGetInteger(fs->fonts[i], FC_WIDTH, 0, &x) == FcResultMatch) + //printf(" - width: %d\n", x); + // XXX deal with font-stretch stuff later + } + + if (pat) + FcPatternDestroy(pat); + if (os) + FcObjectSetDestroy(os); + if (fs) + FcFontSetDestroy(fs); + + return sFontconfigUtils->UpdateFontList(); +} + +nsresult +gfxPlatformGtk::ResolveFontName(const nsAString& aFontName, + FontResolverCallback aCallback, + void *aClosure, + PRBool& aAborted) +{ + + nsAutoString name(aFontName); + /* FIXME: DFB */ + //ToLowerCase(name); + + nsRefPtr ff; + if (gPlatformFonts->Get(name, &ff) || + gPlatformFontAliases->Get(name, &ff)) { + aAborted = !(*aCallback)(ff->mName, aClosure); + return NS_OK; + } + + nsCAutoString utf8Name = NS_ConvertUTF16toUTF8(aFontName); + + FcPattern *npat = FcPatternCreate(); + FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get()); + FcObjectSet *nos = FcObjectSetBuild(FC_FAMILY, NULL); + FcFontSet *nfs = FcFontList(NULL, npat, nos); + + for (int k = 0; k < nfs->nfont; k++) { + FcChar8 *str; + if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch) + continue; + nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast(str))); + /* FIXME: DFB */ + //ToLowerCase(altName); + if (gPlatformFonts->Get(altName, &ff)) { + //printf("Adding alias: %s -> %s\n", utf8Name.get(), str); + gPlatformFontAliases->Put(name, ff); + aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast(str))), aClosure); + goto DONE; + } + } + + FcPatternDestroy(npat); + FcObjectSetDestroy(nos); + FcFontSetDestroy(nfs); + + { + npat = FcPatternCreate(); + FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get()); + FcPatternDel(npat, FC_LANG); + FcConfigSubstitute(NULL, npat, FcMatchPattern); + FcDefaultSubstitute(npat); + + nos = FcObjectSetBuild(FC_FAMILY, NULL); + nfs = FcFontList(NULL, npat, nos); + + FcResult fresult; + + FcPattern *match = FcFontMatch(NULL, npat, &fresult); + if (match) + FcFontSetAdd(nfs, match); + + for (int k = 0; k < nfs->nfont; k++) { + FcChar8 *str; + if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch) + continue; + nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast(str))); + /* FIXME: DFB */ + //ToLowerCase(altName); + if (gPlatformFonts->Get(altName, &ff)) { + //printf("Adding alias: %s -> %s\n", utf8Name.get(), str); + gPlatformFontAliases->Put(name, ff); + aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast(str))), aClosure); + goto DONE; + } + } + } + DONE: + FcPatternDestroy(npat); + FcObjectSetDestroy(nos); + FcFontSetDestroy(nfs); + + return NS_OK; +} + +nsresult +gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) +{ + return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName); +} + +gfxFontGroup * +gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies, + const gfxFontStyle *aStyle) +{ + return new gfxFT2FontGroup(aFamilies, aStyle); +} + +#endif + + /* static */ void gfxPlatformGtk::InitDPI() { +#ifdef MOZ_PANGO PangoContext *context = gdk_pango_context_get (); sDPI = pango_cairo_context_get_resolution (context); g_object_unref (context); +#endif if (sDPI <= 0) { // Fall back to something sane @@ -272,6 +554,7 @@ gfxPlatformGtk::InitDPI() cmsHPROFILE gfxPlatformGtk::GetPlatformCMSOutputProfile() { +#ifdef MOZ_X11 const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA"; const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE"; @@ -393,5 +676,64 @@ gfxPlatformGtk::GetPlatformCMSOutputProfile() return profile; } } +#endif + return nsnull; } + + +#ifndef MOZ_PANGO +FT_Library +gfxPlatformGtk::GetFTLibrary() +{ + return gPlatformFTLibrary; +} + +FontFamily * +gfxPlatformGtk::FindFontFamily(const nsAString& aName) +{ + nsAutoString name(aName); + /* FIXME: DFB */ + //ToLowerCase(name); + + nsRefPtr ff; + if (!gPlatformFonts->Get(name, &ff)) { + return nsnull; + } + return ff.get(); +} + +FontEntry * +gfxPlatformGtk::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle) +{ + nsRefPtr ff = FindFontFamily(aName); + if (!ff) + return nsnull; + + return ff->FindFontEntry(aFontStyle); +} +#endif + + +void +gfxPlatformGtk::SetGdkDrawable(gfxASurface *target, + GdkDrawable *drawable) +{ + if (target->CairoStatus()) + return; + + cairo_surface_set_user_data (target->CairoSurface(), + &cairo_gdk_drawable_key, + drawable, + NULL); +} + +GdkDrawable * +gfxPlatformGtk::GetGdkDrawable(gfxASurface *target) +{ + if (target->CairoStatus()) + return nsnull; + + return (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(), + &cairo_gdk_drawable_key); +}