diff options
Diffstat (limited to 'firefox-2.0-pango-printing.patch')
-rw-r--r-- | firefox-2.0-pango-printing.patch | 4586 |
1 files changed, 0 insertions, 4586 deletions
diff --git a/firefox-2.0-pango-printing.patch b/firefox-2.0-pango-printing.patch deleted file mode 100644 index 0490892..0000000 --- a/firefox-2.0-pango-printing.patch +++ /dev/null @@ -1,4586 +0,0 @@ -Patch for Firefox 1.5.0.7 to add support for printing via Pango. -This also implements printing MathML via Pango, and prints bitmap -fonts too. - -Authors: - Behdad Esfahbod - Chris Blizzard - Akira TAGOH - -Index: gfx/src/freetype/nsFreeType.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.cpp,v -retrieving revision 1.28 -diff -u -p -d -r1.28 nsFreeType.cpp ---- gfx/src/freetype/nsFreeType.cpp 13 Jul 2005 18:21:10 -0000 1.28 -+++ gfx/src/freetype/nsFreeType.cpp 23 Oct 2006 17:37:09 -0000 -@@ -123,6 +123,8 @@ FtFuncList nsFreeType2::FtFuncs [] = { - // #endif - {"FT_Get_First_Char", NS_FT2_OFFSET(nsFT_Get_First_Char), PR_FALSE}, - {"FT_Get_Next_Char", NS_FT2_OFFSET(nsFT_Get_Next_Char), PR_FALSE}, -+ {"FT_Has_PS_Glyph_Names", NS_FT2_OFFSET(nsFT_Has_PS_Glyph_Names), PR_FALSE}, -+ {"FT_Get_Glyph_Name", NS_FT2_OFFSET(nsFT_Get_Glyph_Name), PR_TRUE}, - {nsnull, 0, 0} - }; - -@@ -388,6 +390,22 @@ nsFreeType2::GetNextChar(FT_Face face, F - } - - NS_IMETHODIMP -+nsFreeType2::HasPSGlyphNames(FT_Face face, FT_Int *result) -+{ -+ // call the FreeType2 function via the function pointer -+ *result = nsFT_Has_PS_Glyph_Names(face); -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFreeType2::GetGlyphName(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max) -+{ -+ // call the FreeType2 function via the function pointer -+ FT_Error error = nsFT_Get_Glyph_Name(face, glyph_index, buffer, buffer_max); -+ return error ? NS_ERROR_FAILURE : NS_OK; -+} -+ -+NS_IMETHODIMP - nsFreeType2::SupportsExtFunc(PRBool *res) - { - *res = gHasExtFunc; -Index: gfx/src/freetype/nsFreeType.h -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.h,v -retrieving revision 1.18 -diff -u -p -d -r1.18 nsFreeType.h ---- gfx/src/freetype/nsFreeType.h 1 May 2005 17:36:19 -0000 1.18 -+++ gfx/src/freetype/nsFreeType.h 23 Oct 2006 17:37:09 -0000 -@@ -52,6 +52,7 @@ - #include FT_CACHE_H - #include FT_CACHE_IMAGE_H - #include FT_TRUETYPE_TABLES_H -+#include FT_TYPE1_TABLES_H - #include "nsIFreeType2.h" - - typedef struct FT_FaceRec_* FT_Face; -@@ -138,6 +139,8 @@ typedef FT_Error (*FT_Glyph_To_Bitmap_t) - - typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face, FT_UInt*); - typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face, FT_ULong, FT_UInt*); -+typedef FT_Int (*FT_Has_PS_Glyph_Names_t)(FT_Face); -+typedef FT_Error (*FT_Get_Glyph_Name_t)(FT_Face, FT_UInt, FT_Pointer, FT_UInt); - - class nsFreeTypeFace; - -@@ -193,11 +196,13 @@ protected: - // #endif - FT_Get_First_Char_t nsFT_Get_First_Char; - FT_Get_Next_Char_t nsFT_Get_Next_Char; -+ FT_Has_PS_Glyph_Names_t nsFT_Has_PS_Glyph_Names; -+ FT_Get_Glyph_Name_t nsFT_Get_Glyph_Name; - - // this array needs to be big enough to hold all the function pointers - // plus one extra for the null at the end - // #ifdef MOZ_SVG -- static FtFuncList FtFuncs[24]; -+ static FtFuncList FtFuncs[28]; - // #else - // static FtFuncList FtFuncs[20]; - // #endif -Index: gfx/src/ps/Makefile.in -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/Makefile.in,v -retrieving revision 1.57.8.1 -diff -d -u -p -r1.57.8.1 Makefile.in ---- gfx/src/ps/Makefile.in 17 Jun 2006 15:16:14 -0000 1.57.8.1 -+++ gfx/src/ps/Makefile.in 24 Oct 2006 18:36:45 -0000 -@@ -98,6 +98,15 @@ EXTRA_DSO_LDOPTS = \ - $(MOZ_UNICHARUTIL_LIBS) \ - $(NULL) - -+ifdef MOZ_ENABLE_PANGO -+CPPSRCS += \ -+ nsFontMetricsPSPango.cpp \ -+ mozilla-ps-decoder.cpp -+EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) -+CXXFLAGS += $(MOZ_PANGO_CFLAGS) -+CFLAGS += $(MOZ_PANGO_CFLAGS) -+endif -+ - ifdef MOZ_ENABLE_XFT - EXTRA_DSO_LDOPTS += \ - $(MOZ_XFT_LIBS) \ -@@ -105,7 +114,7 @@ EXTRA_DSO_LDOPTS += \ - $(NULL) - endif - --ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)) -+ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)$(MOZ_ENABLE_PANGO)) - CPPSRCS += \ - nsType1.cpp \ - $(NULL) -Index: gfx/src/ps/mozilla-ps-decoder.cpp -=================================================================== -RCS file: gfx/src/ps/mozilla-ps-decoder.cpp -diff -N gfx/src/ps/mozilla-ps-decoder.cpp ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ gfx/src/ps/mozilla-ps-decoder.cpp 23 Oct 2006 17:37:10 -0000 -@@ -0,0 +1,376 @@ -+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=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.org code. -+ * -+ * The Initial Developer of the Original Code is Christopher Blizzard -+ * <blizzard@mozilla.org>. Portions created by the Initial Developer -+ * are Copyright (C) 2004 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 ***** */ -+ -+#define PANGO_ENABLE_BACKEND -+#define PANGO_ENABLE_ENGINE -+ -+#include "mozilla-ps-decoder.h" -+#include <pango/pangofc-fontmap.h> -+#include <pango/pangofc-font.h> -+ -+#include "nsString.h" -+#include "nsIPersistentProperties2.h" -+#include "nsNetUtil.h" -+#include "nsReadableUtils.h" -+#include "nsICharsetConverterManager.h" -+#include "nsICharRepresentable.h" -+#include "nsCompressedCharMap.h" -+ -+#undef DEBUG_CUSTOM_ENCODER -+ -+G_DEFINE_TYPE (MozillaPSDecoder, mozilla_ps_decoder, PANGO_TYPE_FC_DECODER) -+ -+MozillaPSDecoder *mozilla_ps_decoder_new (void); -+ -+static FcCharSet *mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder, -+ PangoFcFont *fcfont); -+static PangoGlyph mozilla_ps_decoder_get_glyph (PangoFcDecoder *decoder, -+ PangoFcFont *fcfont, -+ guint32 wc); -+ -+static PangoFcDecoder *mozilla_find_ps_decoder (FcPattern *pattern, -+ gpointer user_data); -+ -+typedef struct _MozillaPSDecoderPrivate MozillaPSDecoderPrivate; -+ -+#define MOZILLA_PS_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderPrivate)) -+ -+struct _MozillaPSDecoderPrivate { -+ char *family; -+ char *encoder; -+ char *cmap; -+ gboolean is_wide; -+ FcCharSet *charset; -+ nsCOMPtr<nsIUnicodeEncoder> uEncoder; -+}; -+ -+static nsICharsetConverterManager *gCharsetManager = NULL; -+ -+static NS_DEFINE_CID(kCharsetConverterManagerCID, -+ NS_ICHARSETCONVERTERMANAGER_CID); -+ -+// Hash tables that hold the custom encodings and custom cmaps used in -+// various fonts. -+static GHashTable *encoder_hash = NULL; -+static GHashTable *cmap_hash = NULL; -+static GHashTable *wide_hash = NULL; -+ -+void -+mozilla_ps_decoder_init (MozillaPSDecoder *decoder) -+{ -+} -+ -+void -+mozilla_ps_decoder_class_init (MozillaPSDecoderClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS(klass); -+ PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass); -+ -+ /* object_class->finalize = test_finalize; */ -+ -+ parent_class->get_charset = mozilla_ps_decoder_get_charset; -+ parent_class->get_glyph = mozilla_ps_decoder_get_glyph; -+ -+ g_type_class_add_private (object_class, sizeof (MozillaPSDecoderPrivate)); -+} -+ -+MozillaPSDecoder * -+mozilla_ps_decoder_new(void) -+{ -+ return (MozillaPSDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL); -+} -+ -+#ifdef DEBUG_CUSTOM_ENCODER -+void -+dump_hash(char *key, char *val, void *arg) -+{ -+ printf("%s -> %s\n", key, val); -+} -+#endif -+ -+/** -+ * mozilla_ps_decoders_init: -+ * -+ * #mozilla_ps_decoders_init: -+ * -+ * This initializes all of the application-specific custom decoders -+ * that Mozilla uses. This should only be called once during the -+ * lifetime of the application. -+ * -+ * Return value: zero on success, not zero on failure. -+ * -+ **/ -+ -+int -+mozilla_ps_decoders_init(PangoFontMap *fontmap) -+{ -+ static PRBool initialized = PR_FALSE; -+ if (initialized) -+ return 0; -+ -+ if (!PANGO_IS_FC_FONT_MAP (fontmap)) -+ return -1; -+ -+ encoder_hash = g_hash_table_new(g_str_hash, g_str_equal); -+ cmap_hash = g_hash_table_new(g_str_hash, g_str_equal); -+ wide_hash = g_hash_table_new(g_str_hash, g_str_equal); -+ -+ PRBool dumb = PR_FALSE; -+ nsCOMPtr<nsIPersistentProperties> props; -+ nsCOMPtr<nsISimpleEnumerator> encodeEnum; -+ -+ NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props), -+ NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties")); -+ -+ if (!props) -+ goto loser; -+ -+ // Enumerate the properties in this file and figure out all of the -+ // fonts for which we have custom encodings. -+ props->Enumerate(getter_AddRefs(encodeEnum)); -+ if (!encodeEnum) -+ goto loser; -+ -+ while (encodeEnum->HasMoreElements(&dumb), dumb) { -+ nsCOMPtr<nsIPropertyElement> prop; -+ encodeEnum->GetNext(getter_AddRefs(prop)); -+ if (!prop) -+ goto loser; -+ -+ nsCAutoString name; -+ prop->GetKey(name); -+ nsAutoString value; -+ prop->GetValue(value); -+ -+ if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) { -+ printf("string doesn't begin with encoding?\n"); -+ continue; -+ } -+ -+ name = Substring(name, 9); -+ -+ if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) { -+ name = Substring(name, 0, name.Length() - 4); -+ -+ // Strip off a .wide if it's there. -+ if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) { -+ g_hash_table_insert(wide_hash, g_strdup(name.get()), -+ g_strdup("wide")); -+ value = Substring(value, 0, name.Length() - 5); -+ } -+ -+ g_hash_table_insert(encoder_hash, -+ g_strdup(name.get()), -+ g_strdup(NS_ConvertUTF16toUTF8(value).get())); -+ } -+ else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) { -+ name = Substring(name, 0, name.Length() - 7); -+ g_hash_table_insert(cmap_hash, -+ g_strdup(name.get()), -+ g_strdup(NS_ConvertUTF16toUTF8(value).get())); -+ } -+ else { -+ printf("unknown suffix used for mapping\n"); -+ } -+ } -+ -+ pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(fontmap), -+ mozilla_find_ps_decoder, -+ NULL, -+ NULL); -+ -+ initialized = PR_TRUE; -+ -+#ifdef DEBUG_CUSTOM_ENCODER -+ printf("*** encoders\n"); -+ g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL); -+ -+ printf("*** cmaps\n"); -+ g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL); -+#endif -+ -+ return 0; -+ -+ loser: -+ return -1; -+} -+ -+static FcCharSet * -+mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder, -+ PangoFcFont *fcfont) -+{ -+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder); -+ -+ if (priv->charset) -+ return priv->charset; -+ -+ // First time this has been accessed. Populate the charset. -+ priv->charset = FcCharSetCreate(); -+ -+ if (!gCharsetManager) { -+ CallGetService(kCharsetConverterManagerCID, &gCharsetManager); -+ } -+ -+ nsCOMPtr<nsIUnicodeEncoder> encoder; -+ nsCOMPtr<nsICharRepresentable> represent; -+ -+ if (!gCharsetManager) -+ goto end; -+ -+ gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder)); -+ if (!encoder) -+ goto end; -+ -+ encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?'); -+ -+ priv->uEncoder = encoder; -+ -+ represent = do_QueryInterface(encoder); -+ if (!represent) -+ goto end; -+ -+ PRUint32 map[UCS2_MAP_LEN]; -+ memset(map, 0, sizeof(map)); -+ -+ represent->FillInfo(map); -+ -+ for (int i = 0; i < NUM_UNICODE_CHARS; i++) { -+ if (IS_REPRESENTABLE(map, i)) -+ FcCharSetAddChar(priv->charset, i); -+ } -+ -+ end: -+ return priv->charset; -+} -+ -+static PangoGlyph -+mozilla_ps_decoder_get_glyph (PangoFcDecoder *decoder, -+ PangoFcFont *fcfont, -+ guint32 wc) -+{ -+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder); -+ -+ PangoGlyph retval = 0; -+ PRUnichar inchar = wc; -+ PRInt32 inlen = 1; -+ char outchar[2] = {0,0}; -+ PRInt32 outlen = 2; -+ -+ priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen); -+ if (outlen != 1) { -+ printf("Warning: mozilla_ps_decoder_get_glyph doesn't support more than one character conversions.\n"); -+ return 0; -+ } -+ -+ FT_Face face = pango_fc_font_lock_face(fcfont); -+ -+#ifdef DEBUG_CUSTOM_ENCODER -+ char *filename; -+ FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename); -+ printf("filename is %s\n", filename); -+#endif -+ -+ // Make sure to set the right charmap before trying to get the -+ // glyph -+ if (priv->cmap) { -+ if (!strcmp(priv->cmap, "mac_roman")) { -+ FT_Select_Charmap(face, ft_encoding_apple_roman); -+ } -+ else if (!strcmp(priv->cmap, "unicode")) { -+ FT_Select_Charmap(face, ft_encoding_unicode); -+ } -+ else { -+ printf("Warning: Invalid charmap entry for family %s\n", -+ priv->family); -+ } -+ } -+ -+ // Standard 8 bit to glyph translation -+ if (!priv->is_wide) { -+ FcChar32 blah = PRUint8(outchar[0]); -+ retval = FT_Get_Char_Index(face, blah); -+#ifdef DEBUG_CUSTOM_ENCODER -+ printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n", -+ wc, outchar[0], blah, retval, (void *)face); -+#endif -+ } -+ else { -+ printf("Warning: We don't support .wide fonts!\n"); -+ retval = 0; -+ } -+ -+ pango_fc_font_unlock_face(fcfont); -+ -+ return retval; -+} -+ -+static PangoFcDecoder * -+mozilla_find_ps_decoder (FcPattern *pattern, gpointer user_data) -+{ -+ // Compare the family name of the font that's been opened to see -+ // if we have a custom decoder. -+ const char *orig = NULL; -+ FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig); -+ -+ nsCAutoString family; -+ family.Assign(orig); -+ -+ family.StripWhitespace(); -+ ToLowerCase(family); -+ -+ char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get()); -+ if (!encoder) -+ return NULL; -+ -+ MozillaPSDecoder *decoder = mozilla_ps_decoder_new(); -+ -+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder); -+ -+ priv->family = g_strdup(family.get()); -+ priv->encoder = g_strdup(encoder); -+ -+ char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get()); -+ if (cmap) -+ priv->cmap = g_strdup(cmap); -+ -+ char *wide = (char *)g_hash_table_lookup(wide_hash, family.get()); -+ if (wide) -+ priv->is_wide = TRUE; -+ -+ return PANGO_FC_DECODER(decoder); -+} -Index: gfx/src/ps/mozilla-ps-decoder.h -=================================================================== -RCS file: gfx/src/ps/mozilla-ps-decoder.h -diff -N gfx/src/ps/mozilla-ps-decoder.h ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ gfx/src/ps/mozilla-ps-decoder.h 23 Oct 2006 17:37:10 -0000 -@@ -0,0 +1,72 @@ -+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=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.org code. -+ * -+ * The Initial Developer of the Original Code is Christopher Blizzard -+ * <blizzard@mozilla.org>. Portions created by the Initial Developer -+ * are Copyright (C) 2004 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 ***** */ -+ -+#ifndef _MOZILLA_PS_DECODER_H -+#define _MOZILLA_PS_DECODER_H -+ -+#include <pango/pangofc-decoder.h> -+ -+G_BEGIN_DECLS -+ -+#define MOZILLA_TYPE_DECODER (mozilla_ps_decoder_get_type()) -+#define MOZILLA_PS_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaPSDecoder)) -+#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER)) -+ -+typedef struct _MozillaPSDecoder MozillaPSDecoder; -+typedef struct _MozillaPSDecoderClass MozillaPSDecoderClass; -+ -+#define MOZILLA_PS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass)) -+#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER)) -+#define MOZILLA_PS_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass)) -+ -+struct _MozillaPSDecoder -+{ -+ PangoFcDecoder parent_instance; -+}; -+ -+struct _MozillaPSDecoderClass -+{ -+ PangoFcDecoderClass parent_class; -+}; -+ -+GType mozilla_ps_decoder_get_type (void); -+int mozilla_ps_decoders_init (PangoFontMap *fontmap); -+ -+G_END_DECLS -+ -+#endif /*_MOZILLA_PS_DECODER_H */ -Index: gfx/src/ps/nsDeviceContextPS.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsDeviceContextPS.cpp,v -retrieving revision 1.73 -diff -u -p -d -r1.73 nsDeviceContextPS.cpp ---- gfx/src/ps/nsDeviceContextPS.cpp 21 May 2005 15:33:08 -0000 1.73 -+++ gfx/src/ps/nsDeviceContextPS.cpp 23 Oct 2006 17:37:10 -0000 -@@ -58,12 +58,15 @@ - #include "nsIPref.h" - #include "nsString.h" - #include "nsFontMetricsPS.h" -+#ifdef MOZ_ENABLE_PANGO -+#include "nsFontMetricsPSPango.h" -+#endif - #include "nsPostScriptObj.h" - #include "nspr.h" - #include "nsILanguageAtomService.h" - #include "nsPrintJobPS.h" - #include "nsPrintJobFactoryPS.h" --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - #include "nsType1.h" - #endif - -@@ -223,7 +226,7 @@ nsDeviceContextPS::InitDeviceContextPS(n - - nsresult rv; - nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv)); --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - if (NS_SUCCEEDED(rv)) { - rv = pref->GetBoolPref("font.FreeType2.printing", &mFTPEnable); - if (NS_FAILED(rv)) -@@ -469,7 +472,7 @@ NS_IMETHODIMP nsDeviceContextPS::EndDocu - NS_ASSERTION(submitFP, "No print job submission handle"); - - // Start writing the print job to the job handler --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - mPSObj->write_prolog(submitFP, mFTPEnable); - #else - mPSObj->write_prolog(submitFP); -@@ -550,15 +553,52 @@ public: - virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** aResult); - }; - -+#if defined(MOZ_ENABLE_PANGO) -+PRBool -+NS_IsPangoEnabled(void) -+{ -+ static PRBool beenHere; -+ static PRBool pangoEnabled; -+ -+ if (!beenHere) { -+ beenHere = PR_TRUE; -+ -+ char *val = PR_GetEnv("MOZ_DISABLE_PANGO"); -+ pangoEnabled = !(val); -+ -+ if (pangoEnabled) { -+ nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID); -+ if (prefService) -+ prefService->SetDefaultCharPref("general.useragent.extra.pango", -+ "pango-text"); -+ } -+ } -+ -+ return pangoEnabled; -+} -+#endif - - nsresult nsFontCachePS::CreateFontMetricsInstance(nsIFontMetrics** aResult) - { - NS_PRECONDITION(aResult, "null out param"); -- nsIFontMetrics *fm = new nsFontMetricsPS(); -- if (!fm) -- return NS_ERROR_OUT_OF_MEMORY; -- NS_ADDREF(fm); -- *aResult = fm; -+#ifdef MOZ_ENABLE_PANGO -+ if (NS_IsPangoEnabled()) -+ { -+ nsIFontMetrics *fm = new nsFontMetricsPSPango(); -+ if (!fm) -+ return NS_ERROR_OUT_OF_MEMORY; -+ NS_ADDREF(fm); -+ *aResult = fm; -+ } -+ else -+#endif -+ { -+ nsIFontMetrics *fm = new nsFontMetricsPS(); -+ if (!fm) -+ return NS_ERROR_OUT_OF_MEMORY; -+ NS_ADDREF(fm); -+ *aResult = fm; -+ } - return NS_OK; - } - -Index: gfx/src/ps/nsFontMetricsPS.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.cpp,v -retrieving revision 1.57.16.2 -diff -u -p -d -r1.57.16.2 nsFontMetricsPS.cpp ---- gfx/src/ps/nsFontMetricsPS.cpp 7 May 2006 02:01:25 -0000 1.57.16.2 -+++ gfx/src/ps/nsFontMetricsPS.cpp 23 Oct 2006 17:37:11 -0000 -@@ -461,6 +461,239 @@ nsFontMetricsPS :: GetStringWidth(const - return NS_OK; - } - -+nsresult -+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); -+ // When FT2 printing is enabled, we don't need to set langgroup -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) { -+#endif -+ nsCOMPtr<nsIAtom> langGroup; -+ GetLangGroup(getter_AddRefs(langGroup)); -+ psObj->setlanggroup(langGroup); -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+ } -+#endif -+ -+ if (aLength == 0) -+ return NS_OK; -+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this); -+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); -+ fontPS->SetupFont(aContext); -+ -+ PRUint32 i, start = 0; -+ for (i=0; i<aLength; i++) { -+ nsFontPS* fontThisChar; -+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this); -+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); -+ if (fontThisChar != fontPS) { -+ // draw text up to this point -+ aX += DrawString(aString+start, i-start, aX, aY, fontPS, -+ aSpacing?aSpacing+start:nsnull, aContext); -+ start = i; -+ -+ // setup for following text -+ fontPS = fontThisChar; -+ fontPS->SetupFont(aContext); -+ } -+ } -+ -+ // draw the last part -+ if (aLength-start) -+ DrawString(aString+start, aLength-start, aX, aY, fontPS, -+ aSpacing?aSpacing+start:nsnull, aContext); -+ -+ return NS_OK; -+} -+ -+nsresult -+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ PRInt32 aFontID, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+ // When FT2 printing is enabled, we don't need to set langgroup -+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) { -+#endif -+ nsCOMPtr<nsIAtom> langGroup = nsnull; -+ GetLangGroup(getter_AddRefs(langGroup)); -+ psObj->setlanggroup(langGroup); -+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -+ } -+#endif -+ -+ /* build up conversion table */ -+ psObj->preshow(aString, aLength); -+ -+ if (aLength == 0) -+ return NS_OK; -+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this); -+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); -+ fontPS->SetupFont(aContext); -+ -+ PRUint32 i, start = 0; -+ for (i=0; i<aLength; i++) { -+ nsFontPS* fontThisChar; -+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this); -+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); -+ if (fontThisChar != fontPS) { -+ // draw text up to this point -+ aX += DrawString(aString+start, i-start, aX, aY, fontPS, -+ aSpacing?aSpacing+start:nsnull, aContext); -+ start = i; -+ -+ // setup for following text -+ fontPS = fontThisChar; -+ fontPS->SetupFont(aContext); -+ } -+ } -+ -+ // draw the last part -+ if (aLength-start) -+ DrawString(aString+start, aLength-start, aX, aY, fontPS, -+ aSpacing?aSpacing+start:nsnull, aContext); -+ -+ return NS_OK; -+} -+ -+PRInt32 -+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, nsFontPS* aFontPS, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ nscoord width = 0; -+ PRInt32 x = aX; -+ PRInt32 y = aY; -+ -+ PRInt32 dxMem[500]; -+ PRInt32* dx0 = 0; -+ if (aSpacing) { -+ dx0 = dxMem; -+ if (aLength > 500) { -+ dx0 = new PRInt32[aLength]; -+ NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY); -+ } -+ aContext->GetTranMatrix()->ScaleXCoords(aSpacing, aLength, dx0); -+ } -+ -+ aContext->GetTranMatrix()->TransformCoord(&x, &y); -+ width = aFontPS->DrawString(aContext, x, y, aString, aLength); -+ -+ if ((aSpacing) && (dx0 != dxMem)) { -+ delete [] dx0; -+ } -+ -+ return width; -+} -+ -+ -+PRInt32 -+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength, -+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ nscoord width = 0; -+ PRInt32 x = aX; -+ PRInt32 y = aY; -+ -+ if (aSpacing) { -+ // Slow, but accurate rendering -+ const PRUnichar* end = aString + aLength; -+ while (aString < end){ -+ x = aX; -+ y = aY; -+ aContext->GetTranMatrix()->TransformCoord(&x, &y); -+ aFontPS->DrawString(aContext, x, y, aString, 1); -+ aX += *aSpacing++; -+ aString++; -+ } -+ width = aX; -+ } else { -+ aContext->GetTranMatrix()->TransformCoord(&x, &y); -+ width = aFontPS->DrawString(aContext, x, y, aString, aLength); -+ } -+ -+ return width; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPS::GetTextDimensions(const char* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID) -+{ -+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions"); -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPS::GetTextDimensions(const PRUnichar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID) -+{ -+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions"); -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPS :: GetTextDimensions(const char* aString, PRUint32 aLength, -+ nsTextDimensions& aDimensions) -+{ -+ GetStringWidth(aString, aDimensions.width, aLength); -+ GetMaxAscent(aDimensions.ascent); -+ GetMaxDescent(aDimensions.descent); -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, -+ nsTextDimensions& aDimensions, PRInt32* aFontID) -+{ -+ GetStringWidth(aString, aDimensions.width, aLength); -+ //XXX temporary - bug 96609 -+ GetMaxAscent(aDimensions.ascent); -+ GetMaxDescent(aDimensions.descent); -+ return NS_OK; -+} -+ -+nsresult -+nsFontMetricsPS::GetBoundingMetrics(const char* aString, -+ PRUint32 aLength, -+ nsBoundingMetrics& aBoundingMetrics) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+nsresult -+nsFontMetricsPS::GetBoundingMetrics(const PRUnichar* aString, -+ PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics, -+ PRInt32 *aFontID) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+ - nsFontPS* - nsFontPS::FindFont(char aChar, const nsFont& aFont, - nsFontMetricsPS* aFontMetrics) -@@ -1128,23 +1361,38 @@ nsFontPSXft::DrawString(nsRenderingConte - PRUint32 start = 0; - PRUint32 i; - -+ FT_Face face = getFTFace(); -+ if (!face) { -+ NS_WARNING("Failed to get FT Face in nsFontPSXft::DrawString\n"); -+ return 0; -+ } -+ -+ nsValueArray glyphs(PR_UINT16_MAX); -+ - // XXX : ignore surrogate pairs for now -- nsString *subSet = mPSFontGenerator->GetSubset(); - for (i = 0; i < aLength; ++i) { -- currSubFont = mPSFontGenerator->AddToSubset(aString[i]); -+ PRUint32 glyph = FT_Get_Char_Index(face, aString[i]); -+ currSubFont = mPSFontGenerator->AddToGlyphSubset(glyph); -+ -+ // Check if we need to render the current string - if (prevSubFont != currSubFont) { -- if (prevSubFont != -1) -- psObj->show(&aString[start], i - start, *subSet, prevSubFont); -+ if (prevSubFont != -1) { -+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont); -+ } - NS_ASSERTION(!mFontNameBase.IsEmpty(), - "font base name shouldn't be empty"); - psObj->setfont(mFontNameBase, mHeight, currSubFont); - prevSubFont = currSubFont; - start = i; -+ glyphs.Clear(); - } -+ -+ glyphs.AppendValue(glyph); - } - -- if (prevSubFont != -1) -- psObj->show(&aString[start], i - start, *subSet, prevSubFont); -+ if (prevSubFont != -1) { -+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont); -+ } - - return GetWidth(aString, aLength); - } -@@ -2278,10 +2526,13 @@ nsFontPSFreeType::GetBoundingMetrics(con - // Implementation of nsPSFontGenerator - nsPSFontGenerator::nsPSFontGenerator() - { -+ mGlyphSubset = new nsValueArray(PR_UINT16_MAX, 40); - } - - nsPSFontGenerator::~nsPSFontGenerator() - { -+ if (mGlyphSubset) -+ delete mGlyphSubset; - } - - void nsPSFontGenerator::GeneratePSFont(FILE* aFile) -@@ -2289,24 +2540,29 @@ void nsPSFontGenerator::GeneratePSFont(F - NS_ERROR("should never call nsPSFontGenerator::GeneratePSFont"); - } - --// Add a Unicode character to mSubset which will be divided into --// multiple chunks (subfonts) of 255 (kSubFontSize) characters each. --// Each chunk will be converted to a Type 1 font. Return the index of --// a subfont (chunk) this character belongs to. -+// Add a glyph offset to mSubset which will be divided into multiple -+// chunks (subfonts) of 255 (kSubFontSize) glyphs each. Each chunk -+// will then be converted into a Type 1 font. Return the index of a -+// subfont (chunk) this glyph belongs to. - PRInt32 --nsPSFontGenerator::AddToSubset(PRUnichar aChar) -+nsPSFontGenerator::AddToGlyphSubset(PRUint32 aGlyph) - { -- PRInt32 index = mSubset.FindChar(aChar); -- if (index == kNotFound) { -- mSubset.Append(aChar); -- index = mSubset.Length() - 1; -+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph); -+ if (index == NSVALUEARRAY_INVALID) { -+ mGlyphSubset->AppendValue(aGlyph); -+ index = mGlyphSubset->Count() - 1; - } -+ - return index / kSubFontSize; - } - --nsString *nsPSFontGenerator::GetSubset() -+PRInt32 -+nsPSFontGenerator::InSubsetIndexOf(PRUint32 aGlyph) - { -- return &mSubset; -+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph); -+ if (index == NSVALUEARRAY_INVALID) -+ return 0; -+ return (index % kSubFontSize) + 1; - } - - #ifdef MOZ_ENABLE_XFT -@@ -2353,8 +2609,8 @@ void nsXftType1Generator::GeneratePSFont - } - - int wmode = 0; -- if (!mSubset.IsEmpty()) -- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile); -+ if (mGlyphSubset->Count()) -+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); - } - - #else -@@ -2402,8 +2658,8 @@ void nsFT2Type1Generator::GeneratePSFont - return; - - int wmode = 0; -- if (!mSubset.IsEmpty()) -- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile); -+ if (mGlyphSubset->Count()) -+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); - } - - #endif //MOZ_ENABLE_FREETYPE2 -Index: gfx/src/ps/nsFontMetricsPS.h -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.h,v -retrieving revision 1.31 -diff -u -p -d -r1.31 nsFontMetricsPS.h ---- gfx/src/ps/nsFontMetricsPS.h 28 Jun 2005 18:29:10 -0000 1.31 -+++ gfx/src/ps/nsFontMetricsPS.h 23 Oct 2006 17:37:11 -0000 -@@ -66,6 +66,7 @@ - #endif - #include "nsVoidArray.h" - #include "nsHashtable.h" -+#include "nsValueArray.h" - - class nsPSFontGenerator; - class nsDeviceContextPS; -@@ -108,6 +109,65 @@ public: - NS_IMETHOD GetFontHandle(nsFontHandle &aHandle); - NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength); - NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength); -+ -+ NS_IMETHOD GetTextDimensions(const char* aString, -+ PRUint32 aLength, -+ nsTextDimensions& aDimensions); -+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, -+ PRUint32 aLength, -+ nsTextDimensions& aDimensions, -+ PRInt32* aFontID); -+ NS_IMETHOD GetTextDimensions(const char* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID); -+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID); -+#ifdef MOZ_MATHML -+ NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics); -+ NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString, -+ PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics, -+ PRInt32 *aFontID); -+#endif /* MOZ_MATHML */ -+ -+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ PRInt32 aFontID, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ -+protected: -+ PRInt32 DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, nsFontPS* aFontPS, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength, -+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ -+public: -+ -+ virtual PRUint32 GetHints (void) { return 0; } -+ - - inline void SetXHeight(nscoord aXHeight) { mXHeight = aXHeight; }; - inline void SetSuperscriptOffset(nscoord aSuperscriptOffset) { mSuperscriptOffset = aSuperscriptOffset; }; -@@ -455,16 +515,14 @@ public: - nsPSFontGenerator(); - virtual ~nsPSFontGenerator(); - virtual void GeneratePSFont(FILE* aFile); -- PRInt32 AddToSubset(PRUnichar aChar); -- nsString *GetSubset(); -+ PRInt32 AddToGlyphSubset(PRUint32 aGlyph); -+ PRInt32 InSubsetIndexOf(PRUint32 aGlyph); - - // 256 (PS type 1 encoding vector size) - 1 (1 is for mandatory /.notdef) - const static PRUint16 kSubFontSize; - - protected: -- // XXX To support non-BMP characters, we may have to use -- // nsValueArray with PRUint32 -- nsString mSubset; -+ nsValueArray *mGlyphSubset; - }; - - -Index: gfx/src/ps/nsFontMetricsPSPango.cpp -=================================================================== -RCS file: gfx/src/ps/nsFontMetricsPSPango.cpp -diff -N gfx/src/ps/nsFontMetricsPSPango.cpp ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ gfx/src/ps/nsFontMetricsPSPango.cpp 23 Oct 2006 17:37:13 -0000 -@@ -0,0 +1,2107 @@ -+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=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.org code. -+ * -+ * The Initial Developer of the Original Code is Christopher Blizzard -+ * <blizzard@mozilla.org>. Portions created by the Initial Developer -+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Christopher Blizzard <blizzard@mozilla.org> -+ * Behdad Esfahbod <behdad@behdad.org> -+ * -+ * 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 <strings.h> -+#include "nsFont.h" -+#include "nsIDeviceContext.h" -+#include "nsICharsetConverterManager.h" -+#include "nsIPref.h" -+#include "nsServiceManagerUtils.h" -+ -+#define PANGO_ENABLE_BACKEND -+#define PANGO_ENABLE_ENGINE -+ -+#include "nsFontMetricsPSPango.h" -+#include "nsRenderingContextPS.h" -+#include "nsDeviceContextPS.h" -+#include "nsFontConfigUtils.h" -+ -+#include "nsPrintfCString.h" -+#include "nsUnicharUtils.h" -+#include "nsQuickSort.h" -+#include "nsFontConfigUtils.h" -+ -+#include <fontconfig/fontconfig.h> -+#include <pango/pangoft2.h> -+#include <freetype/tttables.h> -+#include "nsType1.h" -+ -+#include "mozilla-ps-decoder.h" -+ -+#define FORCE_PR_LOG -+#include "prlog.h" -+ -+// Globals -+ -+static PRLogModuleInfo *gPangoFontLog; -+static int gNumInstances; -+ -+ -+static void -+default_substitute (FcPattern *pattern, -+ gpointer data) -+{ -+ FcPatternDel (pattern, FC_HINTING); -+ FcPatternAddBool (pattern, FC_HINTING, 0); -+} -+ -+static PangoFontMap * -+get_fontmap (void) -+{ -+ static PangoFontMap *fontmap = NULL; -+ -+ if (!fontmap) { -+ fontmap = pango_ft2_font_map_new (); -+ pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.); -+ pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL); -+ } -+ -+ return fontmap; -+} -+ -+static PangoContext * -+get_context (void) -+{ -+ return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ()); -+} -+ -+// Defines -+ -+// This is the scaling factor that we keep fonts limited to against -+// the display size. If a pixel size is requested that is more than -+// this factor larger than the height of the display, it's clamped to -+// that value instead of the requested size. -+#define FONT_MAX_FONT_SCALE 2 -+ -+static NS_DEFINE_CID(kCharsetConverterManagerCID, -+ NS_ICHARSETCONVERTERMANAGER_CID); -+ -+#ifdef DEBUG -+#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \ -+ printf("0x%x ", ustr[llen]); \ -+ printf("\n"); -+#endif -+ -+// 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)))) -+ -+// Static function decls -+ -+static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup); -+ -+static void FreeGlobals (void); -+ -+static PangoStyle CalculateStyle (PRUint8 aStyle); -+static PangoWeight CalculateWeight (PRUint16 aWeight); -+ -+static nsresult EnumFontsPango (nsIAtom* aLangGroup, const char* aGeneric, -+ PRUint32* aCount, PRUnichar*** aResult); -+static int CompareFontNames (const void* aArg1, const void* aArg2, -+ void* aClosure); -+ -+nsFontMetricsPSPango::nsFontMetricsPSPango() -+{ -+ if (!gPangoFontLog) -+ gPangoFontLog = PR_NewLogModule("PangoFont"); -+ -+ gNumInstances++; -+ -+ mPangoFontDesc = nsnull; -+ mPangoContext = nsnull; -+ mLTRPangoContext = nsnull; -+ mRTLPangoContext = nsnull; -+ mPangoAttrList = nsnull; -+ mIsRTL = PR_FALSE; -+ mPangoSpaceWidth = 0; -+ -+ static PRBool initialized = PR_FALSE; -+ if (initialized) -+ return; -+ -+ // Initialized the custom decoders -+ if (!mozilla_ps_decoders_init(get_fontmap ())) -+ initialized = PR_TRUE; -+} -+ -+nsFontMetricsPSPango::~nsFontMetricsPSPango() -+{ -+ if (mDeviceContext) -+ mDeviceContext->FontMetricsDeleted(this); -+ -+ if (mPangoFontDesc) -+ pango_font_description_free(mPangoFontDesc); -+ -+ if (mLTRPangoContext) -+ g_object_unref(mLTRPangoContext); -+ -+ if (mRTLPangoContext) -+ g_object_unref(mRTLPangoContext); -+ -+ if (mPangoAttrList) -+ pango_attr_list_unref(mPangoAttrList); -+ -+ // XXX clean up all the pango objects -+ -+ if (--gNumInstances == 0) -+ FreeGlobals(); -+} -+ -+ -+NS_IMPL_ISUPPORTS1(nsFontMetricsPSPango, nsIFontMetrics) -+ -+// nsIFontMetrics impl -+ -+NS_IMETHODIMP -+nsFontMetricsPSPango::Init(const nsFont& aFont, nsIAtom* aLangGroup, -+ nsIDeviceContext *aContext) -+{ -+ mFont = aFont; -+ mLangGroup = aLangGroup; -+ -+ // Hang on to the device context -+ mDeviceContext = aContext; -+ -+ mPointSize = NSTwipsToFloatPoints(mFont.size); -+ -+ // enumerate over the font names passed in -+ mFont.EnumerateFamilies(nsFontMetricsPSPango::EnumFontCallback, this); -+ -+ nsCOMPtr<nsIPref> prefService; -+ prefService = do_GetService(NS_PREF_CONTRACTID); -+ if (!prefService) -+ return NS_ERROR_FAILURE; -+ -+ nsXPIDLCString value; -+ const char* langGroup; -+ mLangGroup->GetUTF8String(&langGroup); -+ -+ // Set up the default font name if it's not set -+ if (!mGenericFont) { -+ nsCAutoString name("font.default."); -+ name.Append(langGroup); -+ prefService->CopyCharPref(name.get(), getter_Copies(value)); -+ -+ if (value.get()) -+ mDefaultFont = value.get(); -+ else -+ mDefaultFont = "serif"; -+ -+ mGenericFont = &mDefaultFont; -+ } -+ -+ // set up the minimum sizes for fonts -+ if (mLangGroup) { -+ nsCAutoString name("font.min-size."); -+ -+ if (mGenericFont->Equals("monospace")) -+ name.Append("fixed"); -+ else -+ name.Append("variable"); -+ -+ name.Append(char('.')); -+ name.Append(langGroup); -+ -+ PRInt32 minimumInt = 0; -+ float minimum; -+ nsresult res; -+ res = prefService->GetIntPref(name.get(), &minimumInt); -+ if (NS_FAILED(res)) -+ prefService->GetDefaultIntPref(name.get(), &minimumInt); -+ -+ if (minimumInt < 0) -+ minimumInt = 0; -+ -+ minimum = minimumInt; -+ -+ // The minimum size is specified in pixels, not in points. -+ // Convert the size from pixels to points. -+ minimum = NSTwipsToFloatPoints(NSFloatPixelsToTwips(minimum, mDeviceContext->DevUnitsToAppUnits())); -+ if (mPointSize < minimum) -+ mPointSize = minimum; -+ } -+ -+ // Make sure that the pixel size is at least greater than zero -+ if (mPointSize < 1) { -+#ifdef DEBUG -+ printf("*** Warning: nsFontMetricsPSPango created with point size %f\n", -+ mPointSize); -+#endif -+ mPointSize = 1; -+ } -+ -+ nsresult rv = RealizeFont(); -+ if (NS_FAILED(rv)) -+ return rv; -+ -+ // Cache font metrics for the 'x' character -+ return CacheFontMetrics(); -+} -+ -+nsresult -+nsFontMetricsPSPango::CacheFontMetrics(void) -+{ -+ // Get our scale factor -+ float f; -+ float val; -+ f = mDeviceContext->DevUnitsToAppUnits(); -+ -+ mPangoAttrList = pango_attr_list_new(); -+ -+ GList *items = pango_itemize(mPangoContext, -+ "a", 0, 1, mPangoAttrList, NULL); -+ -+ if (!items) -+ return NS_ERROR_FAILURE; -+ -+ guint nitems = g_list_length(items); -+ if (nitems != 1) -+ return NS_ERROR_FAILURE; -+ -+ PangoItem *item = (PangoItem *)items->data; -+ PangoFcFont *fcfont = PANGO_FC_FONT(item->analysis.font); -+ if (!fcfont) -+ return NS_ERROR_FAILURE; -+ -+ // Get our font face -+ FT_Face face; -+ face = pango_fc_font_lock_face(fcfont); -+ if (!face) -+ return NS_ERROR_NOT_AVAILABLE; -+ -+ TT_OS2 *os2; -+ os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2); -+ -+ // mEmHeight (size in pixels of EM height) -+ int size; -+ if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) != -+ FcResultMatch) { -+ size = 12; -+ } -+ mEmHeight = PR_MAX(1, nscoord(size * f)); -+ -+ // mMaxAscent -+ val = MOZ_FT_TRUNC(face->size->metrics.ascender); -+ mMaxAscent = NSToIntRound(val * f); -+ -+ // mMaxDescent -+ val = -MOZ_FT_TRUNC(face->size->metrics.descender); -+ mMaxDescent = NSToIntRound(val * f); -+ -+ nscoord lineHeight = mMaxAscent + mMaxDescent; -+ -+ // mLeading (needs ascent and descent and EM height) -+ if (lineHeight > mEmHeight) -+ mLeading = lineHeight - mEmHeight; -+ else -+ mLeading = 0; -+ -+ // mMaxHeight (needs ascent and descent) -+ mMaxHeight = lineHeight; -+ -+ // mEmAscent (needs maxascent, EM height, ascent and descent) -+ mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight); -+ -+ // mEmDescent (needs EM height and EM ascent -+ mEmDescent = mEmHeight - mEmAscent; -+ -+ // mMaxAdvance -+ val = MOZ_FT_TRUNC(face->size->metrics.max_advance); -+ mMaxAdvance = NSToIntRound(val * f); -+ -+ // mPangoSpaceWidth -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ pango_layout_set_text(layout, " ", 1); -+ int pswidth, psheight; -+ pango_layout_get_size(layout, &pswidth, &psheight); -+ mPangoSpaceWidth = pswidth; -+ g_object_unref(layout); -+ -+ // mSpaceWidth (width of a space) -+ nscoord tmpWidth; -+ GetWidth(" ", 1, tmpWidth); -+ mSpaceWidth = tmpWidth; -+ -+ // mAveCharWidth (width of an 'average' char) -+ // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents); -+ //rawWidth = extents.width; -+ //mAveCharWidth = NSToCoordRound(rawWidth * f); -+ GetWidth("x", 1, tmpWidth); -+ mAveCharWidth = tmpWidth; -+ -+ // mXHeight (height of an 'x' character) -+ if (pango_fc_font_has_char(fcfont, 'x')) { -+ PangoRectangle rect; -+ PangoGlyph glyph = pango_fc_font_get_glyph (fcfont, 'x'); -+ pango_font_get_glyph_extents (PANGO_FONT (fcfont), glyph, &rect, NULL); -+ mXHeight = NSToIntRound(rect.height * f / PANGO_SCALE); -+ } -+ else { -+ // 56% of ascent, best guess for non-true type or asian fonts -+ mXHeight = nscoord(((float)mMaxAscent) * 0.56 * f); -+ } -+ -+ // mUnderlineOffset (offset for underlines) -+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position, -+ face->size->metrics.y_scale); -+ if (val) { -+ mUnderlineOffset = NSToIntRound(val * f); -+ } -+ else { -+ mUnderlineOffset = -+ -NSToIntRound(PR_MAX(1, floor(0.1 * -+ MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f); -+ } -+ -+ // mUnderlineSize (thickness of an underline) -+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness, -+ face->size->metrics.y_scale); -+ if (val) { -+ mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f))); -+ } -+ else { -+ mUnderlineSize = -+ NSToIntRound(PR_MAX(1, -+ floor(0.05 * MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f); -+ } -+ -+ // mSuperscriptOffset -+ if (os2 && os2->ySuperscriptYOffset) { -+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySuperscriptYOffset, -+ face->size->metrics.y_scale); -+ mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f))); -+ } -+ else { -+ mSuperscriptOffset = mXHeight; -+ } -+ -+ // mSubscriptOffset -+ if (os2 && os2->ySubscriptYOffset) { -+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySubscriptYOffset, -+ face->size->metrics.y_scale); -+ // some fonts have the incorrect sign. -+ val = (val < 0) ? -val : val; -+ mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f))); -+ } -+ else { -+ mSubscriptOffset = mXHeight; -+ } -+ -+ // mStrikeoutOffset -+ mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0); -+ -+ // mStrikeoutSize -+ mStrikeoutSize = mUnderlineSize; -+ -+ pango_fc_font_unlock_face(fcfont); -+ -+ /* -+ printf("%i\n", mXHeight); -+ printf("%i\n", mSuperscriptOffset); -+ printf("%i\n", mSubscriptOffset); -+ printf("%i\n", mStrikeoutOffset); -+ printf("%i\n", mStrikeoutSize); -+ printf("%i\n", mUnderlineOffset); -+ printf("%i\n", mUnderlineSize); -+ printf("%i\n", mMaxHeight); -+ printf("%i\n", mLeading); -+ printf("%i\n", mEmHeight); -+ printf("%i\n", mEmAscent); -+ printf("%i\n", mEmDescent); -+ printf("%i\n", mMaxAscent); -+ printf("%i\n", mMaxDescent); -+ printf("%i\n", mMaxAdvance); -+ printf("%i\n", mSpaceWidth); -+ printf("%i\n", mAveCharWidth); -+ */ -+ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPSPango::Destroy() -+{ -+ mDeviceContext = nsnull; -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPSPango::GetLangGroup(nsIAtom** aLangGroup) -+{ -+ *aLangGroup = mLangGroup; -+ NS_IF_ADDREF(*aLangGroup); -+ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPSPango::GetFontHandle(nsFontHandle &aHandle) -+{ -+ return NS_ERROR_NOT_IMPLEMENTED; -+} -+ -+// nsIFontMetricsPango impl -+NS_IMETHODIMP -+nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength) -+{ -+ return GetWidth (String, (PRUint32) aLength, aWidth); -+} -+ -+NS_IMETHODIMP -+nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength) -+{ -+ return GetWidth (aString, (PRUint32)aLength, aWidth); -+} -+ -+nsresult -+nsFontMetricsPSPango::GetWidth(const char* aString, PRUint32 aLength, -+ nscoord& aWidth) -+{ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ pango_layout_set_text(layout, aString, aLength); -+ -+ if (mPangoSpaceWidth) -+ FixupSpaceWidths(layout, aString); -+ -+ int width, height; -+ -+ pango_layout_get_size(layout, &width, &height); -+ -+ g_object_unref(layout); -+ -+ float f; -+ f = mDeviceContext->DevUnitsToAppUnits(); -+ aWidth = NSToCoordRound(width * f / PANGO_SCALE); -+ -+ // printf("GetWidth (char *) %d\n", aWidth); -+ -+ return NS_OK; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetWidth(const PRUnichar* aString, PRUint32 aLength, -+ nscoord& aWidth) -+{ -+ nsresult rv = NS_OK; -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ gchar *text = g_utf16_to_utf8(aString, aLength, -+ NULL, NULL, NULL); -+ -+ if (!text) { -+ aWidth = 0; -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow"); -+ DUMP_PRUNICHAR(aString, aLength) -+#endif -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ gint width, height; -+ -+ pango_layout_set_text(layout, text, strlen(text)); -+ FixupSpaceWidths(layout, text); -+ pango_layout_get_size(layout, &width, &height); -+ -+ float f; -+ f = mDeviceContext->DevUnitsToAppUnits(); -+ aWidth = NSToCoordRound(width * f / PANGO_SCALE); -+ -+ // printf("GetWidth %d\n", aWidth); -+ -+ loser: -+ g_free(text); -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+ -+nsresult -+nsFontMetricsPSPango :: GetTextDimensions(const char* aString, PRUint32 aLength, -+ nsTextDimensions& aDimensions) -+{ -+ nsresult rv = NS_OK; -+ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ pango_layout_set_text(layout, aString, aLength); -+ FixupSpaceWidths(layout,aString); -+ -+ // Get the logical extents -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ PangoRectangle rect; -+ pango_layout_line_get_extents(line, NULL, &rect); -+ -+ float P2T; -+ P2T = mDeviceContext->DevUnitsToAppUnits(); -+ -+ aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE); -+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE); -+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE); -+ -+ // printf("GetTextDimensions %d %d %d\n", aDimensions.width, -+ //aDimensions.ascent, aDimensions.descent); -+ -+ loser: -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString, -+ PRUint32 aLength, -+ nsTextDimensions& aDimensions, -+ PRInt32* aFontID) -+{ -+ nsresult rv = NS_OK; -+ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ gchar *text = g_utf16_to_utf8(aString, aLength, -+ NULL, NULL, NULL); -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetTextDimensions invalid unicode to follow"); -+ DUMP_PRUNICHAR(aString, aLength) -+#endif -+ aDimensions.width = 0; -+ aDimensions.ascent = 0; -+ aDimensions.descent = 0; -+ -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ -+ pango_layout_set_text(layout, text, strlen(text)); -+ FixupSpaceWidths(layout, text); -+ -+ // Get the logical extents -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ PangoRectangle rect; -+ pango_layout_line_get_extents(line, NULL, &rect); -+ -+ float P2T; -+ P2T = mDeviceContext->DevUnitsToAppUnits(); -+ -+ aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE); -+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE); -+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE); -+ -+ // printf("GetTextDimensions %d %d %d\n", aDimensions.width, -+ //aDimensions.ascent, aDimensions.descent); -+ -+ loser: -+ g_free(text); -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetTextDimensions(const char* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID) -+{ -+ -+ return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, -+ aNumBreaks, aDimensions, aNumCharsFit, -+ aLastWordDimensions); -+ -+} -+ -+nsresult -+nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID) -+{ -+ nsresult rv = NS_OK; -+ PRInt32 curBreak = 0; -+ gchar *curChar; -+ -+ PRInt32 *utf8Breaks = new PRInt32[aNumBreaks]; -+ -+ gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength, -+ NULL, NULL, NULL); -+ -+ curChar = text; -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow"); -+ DUMP_PRUNICHAR(aString, (PRUint32)aLength) -+#endif -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ // Covert the utf16 break offsets to utf8 break offsets -+ for (PRInt32 curOffset=0; curOffset < aLength; -+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { -+ if (aBreaks[curBreak] == curOffset) { -+ utf8Breaks[curBreak] = curChar - text; -+ curBreak++; -+ } -+ -+ if (IS_HIGH_SURROGATE(aString[curOffset])) -+ curOffset++; -+ } -+ -+ // Always catch the last break -+ utf8Breaks[curBreak] = curChar - text; -+ -+#if 0 -+ if (strlen(text) != aLength) { -+ printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text)); -+ DUMP_PRUNICHAR(aString, aLength) -+ DUMP_PRUNICHAR(text, strlen(text)) -+ for (PRInt32 i = 0; i < aNumBreaks; ++i) { -+ printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]); -+ } -+ } -+#endif -+ -+ // We'll use curBreak to indicate which of the breaks end up being -+ // used for the break point for this line. -+ curBreak = 0; -+ rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks, -+ aNumBreaks, aDimensions, aNumCharsFit, -+ aLastWordDimensions); -+ -+ // Figure out which of the breaks we ended up using to convert -+ // back to utf16 - start from the end. -+ for (PRInt32 i = aNumBreaks - 1; i >= 0; --i) { -+ if (utf8Breaks[i] == aNumCharsFit) { -+ // if (aNumCharsFit != aBreaks[i]) -+ // printf("Fixing utf8 -> utf16 %d -> %d\n", aNumCharsFit, aBreaks[i]); -+ aNumCharsFit = aBreaks[i]; -+ break; -+ } -+ } -+ -+ loser: -+ if (text) -+ g_free(text); -+ -+ delete[] utf8Breaks; -+ -+ return rv; -+} -+ -+typedef struct _nsPSPangoRenderer nsPSPangoRenderer; -+typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass; -+ -+struct _nsPSPangoRenderer -+{ -+ PangoRenderer parent_instance; -+ nsRenderingContextPS *psContext; -+ nsFontMetricsPSPango *psPangoFontMetrics; -+ float zoom; -+}; -+ -+struct _nsPSPangoRendererClass -+{ -+ PangoRendererClass parent_class; -+}; -+ -+#define _PS_TYPE_PANGO_RENDERER (_ps_pango_renderer_get_type()) -+#define _PS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer)) -+#define _PS_IS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER)) -+#define _PS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass)) -+#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER)) -+#define _PS_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass)) -+ -+G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER) -+ -+static PangoRenderer * -+get_renderer (void) -+{ -+ static PangoRenderer *renderer = NULL; -+ -+ if (!renderer) -+ renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL); -+ -+ return renderer; -+} -+ -+static void -+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer, -+ PangoFont *font, -+ PangoGlyphString *glyphs, -+ int x, -+ int y); -+ -+static void -+_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass) -+{ -+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); -+ -+ renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs; -+} -+ -+static void -+_ps_pango_renderer_init (nsPSPangoRenderer *renderer) -+{ -+} -+ -+class nsPangoType1Generator : public nsPSFontGenerator { -+public: -+ nsPangoType1Generator(); -+ ~nsPangoType1Generator(); -+ nsresult Init(PangoFont *aFont); -+ void GeneratePSFont(FILE* aFile); -+ -+protected: -+ PangoFont *mFont; -+}; -+ -+nsPangoType1Generator::nsPangoType1Generator() -+{ -+} -+ -+nsresult -+nsPangoType1Generator::Init(PangoFont *aFont) -+{ -+ NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE); -+ mFont = aFont; -+ g_object_ref (mFont); -+ return NS_OK; -+} -+ -+nsPangoType1Generator::~nsPangoType1Generator() -+{ -+ g_object_unref (mFont); -+ mFont = nsnull; -+} -+ -+void nsPangoType1Generator::GeneratePSFont(FILE* aFile) -+{ -+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont); -+ -+ if (face == nsnull) -+ return; -+ -+ int wmode = 0; -+ if (mGlyphSubset->Count()) -+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); -+ -+ pango_fc_font_unlock_face ((PangoFcFont *) mFont); -+} -+ -+typedef struct -+{ -+ nsCString *FontNameBase; -+ nsCStringKey *key; -+ int font_size; -+} PSPangoFontData; -+ -+static void -+ps_pango_font_data_destroy (PSPangoFontData *data) -+{ -+ delete data->key; -+ delete data->FontNameBase; -+ g_free (data); -+} -+ -+static void -+flattenName(nsCString& aString) -+{ -+ nsCString::iterator start, end; -+ aString.BeginWriting(start); -+ aString.EndWriting(end); -+ while(start != end) { -+ if (*start == ' ') -+ *start= '_'; -+ else if (*start == '(') -+ *start = '_'; -+ else if (*start == ')') -+ *start = '_'; -+ ++start; -+ } -+} -+ -+static void -+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer, -+ PangoFont *font, -+ PangoGlyphString *glyphs, -+ int x, -+ int y) -+{ -+ if (!glyphs->num_glyphs) -+ return; -+ -+ static GQuark data_quark = 0; -+ if (!data_quark) -+ data_quark = g_quark_from_static_string ("ps-pango-font-data"); -+ -+ PSPangoFontData *data; -+ if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark))) -+ { -+ data = g_new (PSPangoFontData, 1); -+ -+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font); -+ if (face == nsnull) -+ return; -+ int wmode = 0; -+ data->FontNameBase = new nsCString (); -+ if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) { -+ g_free (data); -+ pango_fc_font_unlock_face ((PangoFcFont *) font); -+ return; -+ } -+ pango_fc_font_unlock_face ((PangoFcFont *) font); -+ -+ PangoFontDescription *desc = pango_font_describe (font); -+ data->font_size = pango_font_description_get_size (desc); -+ pango_font_description_free (desc); -+ -+ data->key = new nsCStringKey (*data->FontNameBase); -+ -+ g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy); -+ } -+ -+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer; -+ nsRenderingContextPS *aContext = ps_renderer->psContext; -+ nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics; -+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext()); -+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); -+ nsHashtable *psFGList = dc->GetPSFontGeneratorList(); -+ g_return_if_fail (psFGList); -+ nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key); -+ if (!psFontGen) { -+ nsresult rv; -+ psFontGen = new nsPangoType1Generator; -+ g_return_if_fail (psFontGen); -+ rv = ((nsPangoType1Generator*)psFontGen)->Init(font); -+ if (NS_FAILED(rv)) { -+ delete psFontGen; -+ return; -+ } -+ psFGList->Put(data->key, (void *) psFontGen); -+ } -+ nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE); -+ -+ g_return_if_fail (aContext); -+ g_return_if_fail (psObj); -+ -+ nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE); -+ nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE); -+ psObj->moveto(aX, aY); -+ -+ PRInt32 currSubFont, prevSubFont = -1; -+ PRUint32 i; -+ PangoGlyphString gl; -+ -+ gl.glyphs = glyphs->glyphs; -+ gl.num_glyphs = 0; -+ for (i = 0; i < glyphs->num_glyphs; ++i) { -+ currSubFont = psFontGen->AddToGlyphSubset(glyphs->glyphs[i].glyph >= 0x00ffffff ? 0 : glyphs->glyphs[i].glyph); -+ if (prevSubFont != currSubFont) { -+ if (prevSubFont != -1) -+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont); -+ -+ -+ psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont); -+ prevSubFont = currSubFont; -+ gl.glyphs = glyphs->glyphs + i; -+ gl.num_glyphs = 0; -+ } -+ -+ gl.num_glyphs++; -+ } -+ -+ if (prevSubFont != -1) -+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont); -+} -+ -+static void -+draw_layout_line (int x, int y, PangoLayoutLine *line, nsFontMetricsPSPango *aPSPangoFontMetrics, nsRenderingContextPS *aContext) -+{ -+ PangoRenderer *renderer = get_renderer (); -+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer; -+ ps_renderer->psContext = aContext; -+ ps_renderer->psPangoFontMetrics = aPSPangoFontMetrics; -+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, aPSPangoFontMetrics->GetDeviceContext()); -+ ps_renderer->zoom = dc->DevUnitsToAppUnits(); -+ -+ pango_renderer_draw_layout_line (renderer, line, -+ NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom), -+ NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom)); -+} -+ -+nsresult -+nsFontMetricsPSPango::DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ pango_layout_set_text(layout, aString, aLength); -+ FixupSpaceWidths(layout, aString); -+ -+ int x = aX; -+ int y = aY; -+ -+ aContext->GetTranMatrix()->TransformCoord(&x, &y); -+ -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ if (aSpacing && *aSpacing) { -+ DrawStringSlowly(aString, NULL, aLength, x, y, line, aSpacing, aContext); -+ } -+ else { -+ draw_layout_line (x, y, line, this, aContext); -+ } -+ -+ g_object_unref(layout); -+ -+ return NS_OK; -+} -+ -+nsresult -+nsFontMetricsPSPango::DrawString(const PRUnichar* aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ PRInt32 aFontID, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ nsresult rv = NS_OK; -+ int x = aX; -+ int y = aY; -+ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ gchar *text = g_utf16_to_utf8(aString, aLength, -+ NULL, NULL, NULL); -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::DrawString invalid unicode to follow"); -+ DUMP_PRUNICHAR(aString, aLength) -+#endif -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ pango_layout_set_text(layout, text, strlen(text)); -+ FixupSpaceWidths(layout, text); -+ -+ aContext->GetTranMatrix()->TransformCoord(&x, &y); -+ -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ if (aSpacing && *aSpacing) { -+ DrawStringSlowly(text, aString, aLength, x, y, line, aSpacing, aContext); -+ } -+ else { -+ draw_layout_line (x, y, line, this, aContext); -+ } -+ -+ loser: -+ -+ g_free(text); -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+#ifdef MOZ_MATHML -+nsresult -+nsFontMetricsPSPango::GetBoundingMetrics(const char *aString, PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics) -+{ -+ printf("GetBoundingMetrics (char *)\n"); -+ return NS_ERROR_FAILURE; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetBoundingMetrics(const PRUnichar *aString, -+ PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics, -+ PRInt32 *aFontID) -+{ -+ nsresult rv = NS_OK; -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ gchar *text = g_utf16_to_utf8(aString, aLength, -+ NULL, NULL, NULL); -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetBoundingMetrics invalid unicode to follow"); -+ DUMP_PRUNICHAR(aString, aLength) -+#endif -+ aBoundingMetrics.leftBearing = 0; -+ aBoundingMetrics.rightBearing = 0; -+ aBoundingMetrics.width = 0; -+ aBoundingMetrics.ascent = 0; -+ aBoundingMetrics.descent = 0; -+ -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ pango_layout_set_text(layout, text, -1); -+ FixupSpaceWidths(layout, text); -+ -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ // Get the ink and logical extents -+ PangoRectangle ink, logical; -+ pango_layout_line_get_extents(line, &ink, &logical); -+ -+ float P2T; -+ P2T = mDeviceContext->DevUnitsToAppUnits(); -+ -+ aBoundingMetrics.leftBearing = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE); -+ aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE); -+ aBoundingMetrics.ascent = NSToCoordRound(PANGO_ASCENT(ink) * P2T / PANGO_SCALE); -+ aBoundingMetrics.descent = NSToCoordRound(PANGO_DESCENT(ink) * P2T / PANGO_SCALE); -+ aBoundingMetrics.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE); -+ -+ loser: -+ g_free(text); -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+#endif /* MOZ_MATHML */ -+ -+nsresult -+nsFontMetricsPSPango::SetRightToLeftText(PRBool aIsRTL) -+{ -+ if (aIsRTL) { -+ if (!mRTLPangoContext) { -+ mRTLPangoContext = get_context(); -+ pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL); -+ -+ pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup)); -+ pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc); -+ } -+ mPangoContext = mRTLPangoContext; -+ } -+ else { -+ mPangoContext = mLTRPangoContext; -+ } -+ -+ mIsRTL = aIsRTL; -+ return NS_OK; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetClusterInfo(const PRUnichar *aText, -+ PRUint32 aLength, -+ PRUint8 *aClusterStarts) -+{ -+ nsresult rv = NS_OK; -+ PangoLogAttr *attrs = NULL; -+ gint n_attrs = 0; -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ // Convert the incoming UTF-16 to UTF-8 -+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow"); -+ DUMP_PRUNICHAR(aText, aLength) -+#endif -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ // Set up the pango layout -+ pango_layout_set_text(layout, text, strlen(text)); -+ FixupSpaceWidths(layout, text); -+ -+ // Convert back to UTF-16 while filling in the cluster info -+ // structure. -+ pango_layout_get_log_attrs(layout, &attrs, &n_attrs); -+ -+ for (PRUint32 pos = 0; pos < aLength; pos++) { -+ if (IS_HIGH_SURROGATE(aText[pos])) { -+ aClusterStarts[pos] = 1; -+ pos++; -+ } -+ else { -+ aClusterStarts[pos] = attrs[pos].is_cursor_position; -+ } -+ } -+ -+ loser: -+ if (attrs) -+ g_free(attrs); -+ if (text) -+ g_free(text); -+ if (layout) -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+PRInt32 -+nsFontMetricsPSPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, -+ nsPoint aPt) -+{ -+ int trailing = 0; -+ int inx = 0; -+ const gchar *curChar; -+ PRInt32 retval = 0; -+ -+ float f = mDeviceContext->AppUnitsToDevUnits(); -+ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f); -+ PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f); -+ -+ // Convert the incoming UTF-16 to UTF-8 -+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow"); -+ DUMP_PRUNICHAR(aText, aLength) -+#endif -+ retval = -1; -+ goto loser; -+ } -+ -+ // Set up the pango layout -+ pango_layout_set_text(layout, text, strlen(text)); -+ FixupSpaceWidths(layout, text); -+ -+ pango_layout_xy_to_index(layout, localX, localY, -+ &inx, &trailing); -+ -+ // Convert the index back to the utf-16 index -+ curChar = text; -+ -+ for (PRUint32 curOffset=0; curOffset < aLength; -+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { -+ -+ // Check for a match before checking for a surrogate pair -+ if (curChar - text == inx) { -+ retval = curOffset; -+ break; -+ } -+ -+ if (IS_HIGH_SURROGATE(aText[curOffset])) -+ curOffset++; -+ } -+ -+ // If there was a trailing result, advance the index pointer the -+ // number of characters equal to the trailing result. -+ while (trailing) { -+ retval++; -+ // Yes, this can make aInx > length to indicate the end of the -+ // string. -+ if (retval < (PRInt32)aLength && IS_HIGH_SURROGATE(aText[retval])) -+ retval++; -+ trailing--; -+ } -+ -+ loser: -+ if (text) -+ g_free(text); -+ if (layout) -+ g_object_unref(layout); -+ -+ return retval; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetRangeWidth(const PRUnichar *aText, -+ PRUint32 aLength, -+ PRUint32 aStart, -+ PRUint32 aEnd, -+ PRUint32 &aWidth) -+{ -+ nsresult rv = NS_OK; -+ PRUint32 utf8Start = 0; -+ PRUint32 utf8End = 0; -+ -+ aWidth = 0; -+ -+ // Convert the incoming UTF-16 to UTF-8 -+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); -+ gchar *curChar = text; -+ -+ if (!text) { -+#ifdef DEBUG -+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow"); -+ DUMP_PRUNICHAR(aText, aLength) -+#endif -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ // Convert the utf16 offsets into utf8 offsets -+ for (PRUint32 curOffset = 0; curOffset < aLength; -+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { -+ -+ if (curOffset == aStart) -+ utf8Start = curChar - text; -+ -+ if (curOffset == aEnd) -+ utf8End = curChar - text; -+ -+ if (IS_HIGH_SURROGATE(aText[curOffset])) -+ curOffset++; -+ } -+ -+ // Special case where the end index is the same as the length -+ if (aLength == aEnd) -+ utf8End = strlen(text); -+ -+ rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth); -+ -+ loser: -+ if (text) -+ g_free(text); -+ -+ return rv; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetRangeWidth(const char *aText, -+ PRUint32 aLength, -+ PRUint32 aStart, -+ PRUint32 aEnd, -+ PRUint32 &aWidth) -+{ -+ nsresult rv = NS_OK; -+ int *ranges = NULL; -+ int n_ranges = 0; -+ float f; -+ -+ aWidth = 0; -+ -+ PangoLayout *layout = pango_layout_new(mPangoContext); -+ -+ if (!aText) { -+ rv = NS_ERROR_FAILURE; -+ goto loser; -+ } -+ -+ pango_layout_set_text(layout, aText, aLength); -+ FixupSpaceWidths(layout, aText); -+ -+ PangoLayoutLine *line; -+ if (pango_layout_get_line_count(layout) != 1) { -+ printf("Warning: more than one line!\n"); -+ } -+ line = pango_layout_get_line(layout, 0); -+ -+ pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges); -+ -+ aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]); -+ -+ f = mDeviceContext-> DevUnitsToAppUnits(); -+ aWidth = nscoord(aWidth * f / PANGO_SCALE); -+ -+ loser: -+ if (ranges) -+ g_free(ranges); -+ if (layout) -+ g_object_unref(layout); -+ -+ return rv; -+} -+ -+PRUint32 -+nsFontMetricsPSPango::GetHints(void) -+{ -+ return (NS_RENDERING_HINT_BIDI_REORDERING | -+ NS_RENDERING_HINT_ARABIC_SHAPING | -+ NS_RENDERING_HINT_FAST_MEASURE | -+ NS_RENDERING_HINT_REORDER_SPACED_TEXT | -+ NS_RENDERING_HINT_TEXT_CLUSTERS); -+} -+ -+/* static */ -+nsresult -+nsFontMetricsPSPango::FamilyExists(nsIDeviceContext *aDevice, -+ const nsString &aName) -+{ -+ // fontconfig family name is always in UTF-8 -+ NS_ConvertUTF16toUTF8 name(aName); -+ -+ nsresult rv = NS_ERROR_FAILURE; -+ PangoContext *context = get_context(); -+ PangoFontFamily **familyList; -+ int n; -+ -+ pango_context_list_families(context, &familyList, &n); -+ -+ for (int i=0; i < n; i++) { -+ const char *tmpname = pango_font_family_get_name(familyList[i]); -+ if (!Compare(nsDependentCString(tmpname), name, -+ nsCaseInsensitiveCStringComparator())) { -+ rv = NS_OK; -+ break; -+ } -+ } -+ -+ g_free(familyList); -+ g_object_unref(context); -+ -+ return rv; -+} -+ -+// Private Methods -+ -+nsresult -+nsFontMetricsPSPango::RealizeFont(void) -+{ -+ nsCString familyList; -+ // Create and fill out the font description. -+ mPangoFontDesc = pango_font_description_new(); -+ -+ // Add CSS names - walk the list of fonts, adding the generic as -+ // the last font -+ for (int i=0; i < mFontList.Count(); ++i) { -+ // if this was a generic name, break out of the loop since we -+ // don't want to add it to the pattern yet -+ if (mFontIsGeneric[i]) -+ break;; -+ -+ nsCString *familyName = mFontList.CStringAt(i); -+ familyList.Append(familyName->get()); -+ familyList.Append(','); -+ } -+ -+ // If there's a generic add a pref for the generic if there's one -+ // set. -+ if (mGenericFont && !mFont.systemFont) { -+ nsCString name; -+ name += "font.name."; -+ name += mGenericFont->get(); -+ name += "."; -+ -+ nsString langGroup; -+ mLangGroup->ToString(langGroup); -+ -+ name.AppendWithConversion(langGroup); -+ -+ nsCOMPtr<nsIPref> pref; -+ pref = do_GetService(NS_PREF_CONTRACTID); -+ if (pref) { -+ nsresult rv; -+ nsXPIDLCString value; -+ rv = pref->GetCharPref(name.get(), getter_Copies(value)); -+ -+ // we ignore prefs that have three hypens since they are X -+ // style prefs. -+ if (NS_FFRECountHyphens(value) < 3) { -+ nsCString tmpstr; -+ tmpstr.Append(value); -+ -+ familyList.Append(tmpstr); -+ familyList.Append(','); -+ } -+ } -+ } -+ -+ // Add the generic if there is one. -+ if (mGenericFont && !mFont.systemFont) { -+ familyList.Append(mGenericFont->get()); -+ familyList.Append(','); -+ } -+ -+ // Set the family -+ pango_font_description_set_family(mPangoFontDesc, -+ familyList.get()); -+ -+ // Set the point size -+ pango_font_description_set_size(mPangoFontDesc, -+ (gint)(mPointSize * PANGO_SCALE)); -+ -+ // Set the style -+ pango_font_description_set_style(mPangoFontDesc, -+ CalculateStyle(mFont.style)); -+ -+ // Set the weight -+ pango_font_description_set_weight(mPangoFontDesc, -+ CalculateWeight(mFont.weight)); -+ -+ // Now that we have the font description set up, create the -+ // context. -+ mLTRPangoContext = get_context(); -+ mPangoContext = mLTRPangoContext; -+ -+ // Make sure to set the base direction to LTR - if layout needs to -+ // render RTL text it will use ::SetRightToLeftText() -+ pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR); -+ -+ // Set the pango language now that we have a context -+ pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup)); -+ -+ // And attach the font description to this context -+ pango_context_set_font_description(mPangoContext, mPangoFontDesc); -+ -+ return NS_OK; -+} -+ -+/* static */ -+PRBool -+nsFontMetricsPSPango::EnumFontCallback(const nsString &aFamily, -+ PRBool aIsGeneric, void *aData) -+{ -+ NS_ConvertUTF16toUTF8 name(aFamily); -+ -+ // The newest fontconfig does the full Unicode case folding so that -+ // we're being lazy here by calling |ToLowerCase| after converting -+ // to UTF-8 assuming that in virtually all cases, we just have to -+ // fold [A-Z]. (bug 223653). -+ ToLowerCase(name); -+ nsFontMetricsPSPango *metrics = (nsFontMetricsPSPango *)aData; -+ metrics->mFontList.AppendCString(name); -+ metrics->mFontIsGeneric.AppendElement((void *)aIsGeneric); -+ if (aIsGeneric) { -+ metrics->mGenericFont = -+ metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1); -+ return PR_FALSE; // stop processing -+ } -+ -+ return PR_TRUE; // keep processing -+} -+ -+/* -+ * This is only used when there's per-character spacing happening. -+ * Well, really it can be either line or character spacing but it's -+ * just turtles all the way down! -+ */ -+ -+void -+nsFontMetricsPSPango::DrawStringSlowly(const gchar *aText, -+ const PRUnichar *aOrigString, -+ PRUint32 aLength, -+ gint aX, gint aY, -+ PangoLayoutLine *aLine, -+ const nscoord *aSpacing, -+ nsRenderingContextPS *aContext) -+{ -+ float app2dev; -+ app2dev = mDeviceContext->AppUnitsToDevUnits(); -+ gint offset = 0; -+ -+ /* -+ * We walk the list of glyphs returned in each layout run, -+ * matching up the glyphs with the characters in the source text. -+ * We use the aSpacing argument to figure out where to place those -+ * glyphs. It's important to note that since the string we're -+ * working with is in UTF-8 while the spacing argument assumes -+ * that offset will be part of the UTF-16 string. Logical -+ * attributes in pango are in byte offsets in the UTF-8 string, so -+ * we need to store the offsets based on the UTF-8 string. -+ */ -+ nscoord *utf8spacing = new nscoord[strlen(aText)]; -+ -+ if (aOrigString) { -+ const gchar *curChar = aText; -+ bzero(utf8spacing, sizeof(nscoord) * strlen(aText)); -+ -+ // Covert the utf16 spacing offsets to utf8 spacing offsets -+ for (PRUint32 curOffset=0; curOffset < aLength; -+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { -+ utf8spacing[curChar - aText] = aSpacing[curOffset]; -+ -+ if (IS_HIGH_SURROGATE(aOrigString[curOffset])) -+ curOffset++; -+ } -+ } -+ else { -+ memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength)); -+ } -+ -+ gint curRun = 0; -+ -+ for (GSList *tmpList = aLine->runs; tmpList && tmpList->data; -+ tmpList = tmpList->next, curRun++) { -+ PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data; -+ gint tmpOffset = 0; -+ -+ /* printf(" Rendering run %d: \"%s\"\n", curRun, -+ &aText[layoutRun->item->offset]); */ -+ -+ for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) { -+ /* printf("glyph %d offset %d orig width %d new width %d\n", i, -+ * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset, -+ * layoutRun->glyphs->glyphs[i].geometry.width, -+ * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE)); -+ */ -+ gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] -+ * app2dev * PANGO_SCALE); -+ layoutRun->glyphs->glyphs[i].geometry.width = thisOffset; -+ tmpOffset += thisOffset; -+ } -+ -+ /* printf(" rendering at X coord %d\n", aX + offset); */ -+ offset += tmpOffset; -+ } -+ -+ draw_layout_line (aX, aY, aLine, this, aContext); -+ -+ delete[] utf8spacing; -+} -+ -+nsresult -+nsFontMetricsPSPango::GetTextDimensionsInternal(const gchar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions) -+{ -+ NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array"); -+ -+ // If we need to back up this state represents the last place -+ // we could break. We can use this to avoid remeasuring text -+ PRInt32 prevBreakState_BreakIndex = -1; // not known -+ // (hasn't been computed) -+ nscoord prevBreakState_Width = 0; // accumulated width to this point -+ -+ // Initialize OUT parameters -+ GetMaxAscent(aLastWordDimensions.ascent); -+ GetMaxDescent(aLastWordDimensions.descent); -+ aLastWordDimensions.width = -1; -+ aNumCharsFit = 0; -+ -+ // Iterate each character in the string and determine which font to use -+ nscoord width = 0; -+ PRInt32 start = 0; -+ nscoord aveCharWidth; -+ GetAveCharWidth(aveCharWidth); -+ -+ while (start < aLength) { -+ // Estimate how many characters will fit. Do that by -+ // diving the available space by the average character -+ // width. Make sure the estimated number of characters is -+ // at least 1 -+ PRInt32 estimatedNumChars = 0; -+ -+ if (aveCharWidth > 0) -+ estimatedNumChars = (aAvailWidth - width) / aveCharWidth; -+ -+ if (estimatedNumChars < 1) -+ estimatedNumChars = 1; -+ -+ // Find the nearest break offset -+ PRInt32 estimatedBreakOffset = start + estimatedNumChars; -+ PRInt32 breakIndex; -+ nscoord numChars; -+ -+ // Find the nearest place to break that is less than or equal to -+ // the estimated break offset -+ if (aLength <= estimatedBreakOffset) { -+ // All the characters should fit -+ numChars = aLength - start; -+ breakIndex = aNumBreaks - 1; -+ } -+ else { -+ breakIndex = prevBreakState_BreakIndex; -+ while (((breakIndex + 1) < aNumBreaks) && -+ (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) { -+ ++breakIndex; -+ } -+ -+ if (breakIndex == prevBreakState_BreakIndex) { -+ ++breakIndex; // make sure we advanced past the -+ // previous break index -+ } -+ -+ numChars = aBreaks[breakIndex] - start; -+ } -+ -+ // Measure the text -+ nscoord twWidth = 0; -+ if ((1 == numChars) && (aString[start] == ' ')) -+ GetSpaceWidth(twWidth); -+ else if (numChars > 0) -+ GetWidth(&aString[start], numChars, twWidth); -+ -+ // See if the text fits -+ PRBool textFits = (twWidth + width) <= aAvailWidth; -+ -+ // If the text fits then update the width and the number of -+ // characters that fit -+ if (textFits) { -+ aNumCharsFit += numChars; -+ width += twWidth; -+ start += numChars; -+ -+ // This is a good spot to back up to if we need to so remember -+ // this state -+ prevBreakState_BreakIndex = breakIndex; -+ prevBreakState_Width = width; -+ } -+ else { -+ // See if we can just back up to the previous saved -+ // state and not have to measure any text -+ if (prevBreakState_BreakIndex > 0) { -+ // If the previous break index is just before the -+ // current break index then we can use it -+ if (prevBreakState_BreakIndex == (breakIndex - 1)) { -+ aNumCharsFit = aBreaks[prevBreakState_BreakIndex]; -+ width = prevBreakState_Width; -+ break; -+ } -+ } -+ -+ // We can't just revert to the previous break state -+ if (0 == breakIndex) { -+ // There's no place to back up to, so even though -+ // the text doesn't fit return it anyway -+ aNumCharsFit += numChars; -+ width += twWidth; -+ break; -+ } -+ -+ // Repeatedly back up until we get to where the text -+ // fits or we're all the way back to the first word -+ width += twWidth; -+ while ((breakIndex >= 1) && (width > aAvailWidth)) { -+ twWidth = 0; -+ start = aBreaks[breakIndex - 1]; -+ numChars = aBreaks[breakIndex] - start; -+ -+ if ((1 == numChars) && (aString[start] == ' ')) -+ GetSpaceWidth(twWidth); -+ else if (numChars > 0) -+ GetWidth(&aString[start], numChars, twWidth); -+ width -= twWidth; -+ aNumCharsFit = start; -+ breakIndex--; -+ } -+ break; -+ } -+ } -+ -+ aDimensions.width = width; -+ GetMaxAscent(aDimensions.ascent); -+ GetMaxDescent(aDimensions.descent); -+ -+ /* printf("aDimensions %d %d %d aLastWordDimensions %d %d %d aNumCharsFit %d\n", -+ aDimensions.width, aDimensions.ascent, aDimensions.descent, -+ aLastWordDimensions.width, aLastWordDimensions.ascent, aLastWordDimensions.descent, -+ aNumCharsFit); */ -+ -+ return NS_OK; -+} -+ -+void -+nsFontMetricsPSPango::FixupSpaceWidths (PangoLayout *aLayout, -+ const char *aString) -+{ -+ PangoLayoutLine *line = pango_layout_get_line(aLayout, 0); -+ -+ gint curRun = 0; -+ -+ for (GSList *tmpList = line->runs; tmpList && tmpList->data; -+ tmpList = tmpList->next, curRun++) { -+ PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data; -+ -+ for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) { -+ gint thisOffset = (gint)layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset; -+ if (aString[thisOffset] == ' ') -+ layoutRun->glyphs->glyphs[i].geometry.width = mPangoSpaceWidth; -+ } -+ } -+} -+ -+/* static */ -+PangoLanguage * -+GetPangoLanguage(nsIAtom *aLangGroup) -+{ -+ // Find the FC lang group for this lang group -+ nsCAutoString cname; -+ aLangGroup->ToUTF8String(cname); -+ -+ // see if the lang group needs to be translated from mozilla's -+ // internal mapping into fontconfig's -+ const MozGtkLangGroup *langGroup; -+ langGroup = NS_FindFCLangGroup(cname); -+ -+ // if there's no lang group, just use the lang group as it was -+ // passed to us -+ // -+ // we're casting away the const here for the strings - should be -+ // safe. -+ if (!langGroup) -+ return pango_language_from_string(cname.get()); -+ else if (langGroup->Lang) -+ return pango_language_from_string((char *) langGroup->Lang); -+ -+ return pango_language_from_string("en"); -+} -+ -+/* static */ -+void -+FreeGlobals(void) -+{ -+} -+ -+/* static */ -+PangoStyle -+CalculateStyle(PRUint8 aStyle) -+{ -+ switch(aStyle) { -+ case NS_FONT_STYLE_ITALIC: -+ return PANGO_STYLE_OBLIQUE; -+ break; -+ case NS_FONT_STYLE_OBLIQUE: -+ return PANGO_STYLE_OBLIQUE; -+ break; -+ } -+ -+ return PANGO_STYLE_NORMAL; -+} -+ -+/* static */ -+PangoWeight -+CalculateWeight (PRUint16 aWeight) -+{ -+ /* -+ * weights come in two parts crammed into one -+ * integer -- the "base" weight is weight / 100, -+ * the rest of the value is the "offset" from that -+ * weight -- the number of steps to move to adjust -+ * the weight in the list of supported font weights, -+ * this value can be negative or positive. -+ */ -+ PRInt32 baseWeight = (aWeight + 50) / 100; -+ PRInt32 offset = aWeight - baseWeight * 100; -+ -+ /* clip weights to range 0 to 9 */ -+ if (baseWeight < 0) -+ baseWeight = 0; -+ if (baseWeight > 9) -+ baseWeight = 9; -+ -+ /* Map from weight value to fcWeights index */ -+ static int fcWeightLookup[10] = { -+ 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, -+ }; -+ -+ PRInt32 fcWeight = fcWeightLookup[baseWeight]; -+ -+ /* -+ * adjust by the offset value, make sure we stay inside the -+ * fcWeights table -+ */ -+ fcWeight += offset; -+ -+ if (fcWeight < 0) -+ fcWeight = 0; -+ if (fcWeight > 4) -+ fcWeight = 4; -+ -+ /* Map to final PANGO_WEIGHT value */ -+ static int fcWeights[5] = { -+ 349, -+ 499, -+ 649, -+ 749, -+ 999 -+ }; -+ -+ return (PangoWeight)fcWeights[fcWeight]; -+} -+ -+/* static */ -+nsresult -+EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric, -+ PRUint32* aCount, PRUnichar*** aResult) -+{ -+ FcPattern *pat = NULL; -+ FcObjectSet *os = NULL; -+ FcFontSet *fs = NULL; -+ nsresult rv = NS_ERROR_FAILURE; -+ -+ PRUnichar **array = NULL; -+ PRUint32 narray = 0; -+ PRInt32 serif = 0, sansSerif = 0, monospace = 0, nGenerics; -+ -+ *aCount = 0; -+ *aResult = nsnull; -+ -+ pat = FcPatternCreate(); -+ if (!pat) -+ goto end; -+ -+ os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, NULL); -+ if (!os) -+ goto end; -+ -+ // take the pattern and add the lang group to it -+ if (aLangGroup) -+ NS_AddLangGroup(pat, aLangGroup); -+ -+ // get the font list -+ fs = FcFontList(0, pat, os); -+ -+ if (!fs) -+ goto end; -+ -+ if (!fs->nfont) { -+ rv = NS_OK; -+ goto end; -+ } -+ -+ // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and -+ // "monospace", slightly different from CSS's 5. -+ if (!aGeneric) -+ serif = sansSerif = monospace = 1; -+ else if (!strcmp(aGeneric, "serif")) -+ serif = 1; -+ else if (!strcmp(aGeneric, "sans-serif")) -+ sansSerif = 1; -+ else if (!strcmp(aGeneric, "monospace")) -+ monospace = 1; -+ else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy")) -+ serif = sansSerif = 1; -+ else -+ NS_NOTREACHED("unexpected generic family"); -+ nGenerics = serif + sansSerif + monospace; -+ -+ array = NS_STATIC_CAST(PRUnichar **, -+ nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *))); -+ if (!array) -+ goto end; -+ -+ if (serif) { -+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif")); -+ if (!name) -+ goto end; -+ array[narray++] = name; -+ } -+ -+ if (sansSerif) { -+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif")); -+ if (!name) -+ goto end; -+ array[narray++] = name; -+ } -+ -+ if (monospace) { -+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace")); -+ if (!name) -+ goto end; -+ array[narray++] = name; -+ } -+ -+ for (int i=0; i < fs->nfont; ++i) { -+ char *family; -+ -+ // if there's no family, just move to the next iteration -+ if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, -+ (FcChar8 **) &family) != FcResultMatch) { -+ continue; -+ } -+ -+ // fontconfig always returns family names in UTF-8 -+ PRUnichar* name = UTF8ToNewUnicode(nsDependentCString(family)); -+ -+ if (!name) -+ goto end; -+ -+ array[narray++] = name; -+ } -+ -+ NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*), -+ CompareFontNames, nsnull); -+ -+ *aCount = narray; -+ if (narray) -+ *aResult = array; -+ else -+ nsMemory::Free(array); -+ -+ rv = NS_OK; -+ -+ end: -+ if (NS_FAILED(rv) && array) { -+ while (narray) -+ nsMemory::Free (array[--narray]); -+ nsMemory::Free (array); -+ } -+ if (pat) -+ FcPatternDestroy(pat); -+ if (os) -+ FcObjectSetDestroy(os); -+ if (fs) -+ FcFontSetDestroy(fs); -+ -+ return rv; -+} -+ -+/* static */ -+int -+CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure) -+{ -+ const PRUnichar* str1 = *((const PRUnichar**) aArg1); -+ const PRUnichar* str2 = *((const PRUnichar**) aArg2); -+ -+ return nsCRT::strcmp(str1, str2); -+} -+ -+ -+// nsFontEnumeratorPango class -+ -+nsFontEnumeratorPango::nsFontEnumeratorPango() -+{ -+} -+ -+NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator) -+ -+NS_IMETHODIMP -+nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount, -+ PRUnichar ***aResult) -+{ -+ NS_ENSURE_ARG_POINTER(aResult); -+ *aResult = nsnull; -+ NS_ENSURE_ARG_POINTER(aCount); -+ *aCount = 0; -+ -+ return EnumFontsPango(nsnull, nsnull, aCount, aResult); -+} -+ -+NS_IMETHODIMP -+nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup, -+ const char *aGeneric, -+ PRUint32 *aCount, -+ PRUnichar ***aResult) -+{ -+ NS_ENSURE_ARG_POINTER(aResult); -+ *aResult = nsnull; -+ NS_ENSURE_ARG_POINTER(aCount); -+ *aCount = 0; -+ -+ // aLangGroup=null or "" means any (i.e., don't care) -+ // aGeneric=null or "" means any (i.e, don't care) -+ nsCOMPtr<nsIAtom> langGroup; -+ if (aLangGroup && *aLangGroup) -+ langGroup = do_GetAtom(aLangGroup); -+ const char* generic = nsnull; -+ if (aGeneric && *aGeneric) -+ generic = aGeneric; -+ -+ return EnumFontsPango(langGroup, generic, aCount, aResult); -+} -+ -+NS_IMETHODIMP -+nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup, -+ PRBool *aResult) -+{ -+ NS_ENSURE_ARG_POINTER(aResult); -+ *aResult = PR_FALSE; -+ NS_ENSURE_ARG_POINTER(aLangGroup); -+ -+ *aResult = PR_TRUE; // always return true for now. -+ // Finish me - ftang -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup, -+ const char *aGeneric, -+ PRUnichar **aResult) -+{ -+ NS_ENSURE_ARG_POINTER(aResult); -+ *aResult = nsnull; -+ -+ // Have a look at nsFontEnumeratorXft::GetDefaultFont for some -+ // possible code for this function. -+ -+ return NS_OK; -+} -+ -+NS_IMETHODIMP -+nsFontEnumeratorPango::UpdateFontList(PRBool *_retval) -+{ -+ *_retval = PR_FALSE; // always return false for now -+ return NS_OK; -+} -Index: gfx/src/ps/nsFontMetricsPSPango.h -=================================================================== -RCS file: gfx/src/ps/nsFontMetricsPSPango.h -diff -N gfx/src/ps/nsFontMetricsPSPango.h ---- /dev/null 1 Jan 1970 00:00:00 -0000 -+++ gfx/src/ps/nsFontMetricsPSPango.h 23 Oct 2006 17:37:13 -0000 -@@ -0,0 +1,305 @@ -+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=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.org code. -+ * -+ * The Initial Developer of the Original Code is -+ * Christopher Blizzard <blizzard@mozilla.org>. -+ * Portions created by the Initial Developer are Copyright (C) 2002 -+ * 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 ***** */ -+ -+#ifndef nsFontMetricsPSPango_h__ -+#define nsFontMetricsPSPango_h__ -+ -+#include "nsIFontMetrics.h" -+#include "nsIFontEnumerator.h" -+#include "nsCRT.h" -+#include "nsIAtom.h" -+#include "nsString.h" -+#include "nsVoidArray.h" -+#include "nsFontMetricsPS.h" -+ -+#include <pango/pango.h> -+ -+class nsRenderingContextPS; -+class nsIDrawingSurface; -+ -+class nsFontMetricsPSPango : public nsFontMetricsPS -+{ -+public: -+ nsFontMetricsPSPango(); -+ virtual ~nsFontMetricsPSPango(); -+ -+ NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW -+ -+ // nsISupports -+ NS_DECL_ISUPPORTS -+ -+ // nsIFontMetrics -+ NS_IMETHOD Init (const nsFont& aFont, nsIAtom* aLangGroup, -+ nsIDeviceContext *aContext); -+ NS_IMETHOD Destroy(); -+ NS_IMETHOD GetLangGroup (nsIAtom** aLangGroup); -+ NS_IMETHOD GetFontHandle (nsFontHandle &aHandle); -+ -+ NS_IMETHOD GetXHeight (nscoord& aResult) -+ { aResult = mXHeight; return NS_OK; }; -+ -+ NS_IMETHOD GetSuperscriptOffset (nscoord& aResult) -+ { aResult = mSuperscriptOffset; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetSubscriptOffset (nscoord& aResult) -+ { aResult = mSubscriptOffset; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetStrikeout (nscoord& aOffset, nscoord& aSize) -+ { aOffset = mStrikeoutOffset; -+ aSize = mStrikeoutSize; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetUnderline (nscoord& aOffset, nscoord& aSize) -+ { aOffset = mUnderlineOffset; -+ aSize = mUnderlineSize; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetHeight (nscoord &aHeight) -+ { aHeight = mMaxHeight; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetNormalLineHeight (nscoord &aHeight) -+ { aHeight = mEmHeight + mLeading; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetLeading (nscoord &aLeading) -+ { aLeading = mLeading; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetEmHeight (nscoord &aHeight) -+ { aHeight = mEmHeight; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetEmAscent (nscoord &aAscent) -+ { aAscent = mEmAscent; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetEmDescent (nscoord &aDescent) -+ { aDescent = mEmDescent; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetMaxHeight (nscoord &aHeight) -+ { aHeight = mMaxHeight; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetMaxAscent (nscoord &aAscent) -+ { aAscent = mMaxAscent; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetMaxDescent (nscoord &aDescent) -+ { aDescent = mMaxDescent; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetMaxAdvance (nscoord &aAdvance) -+ { aAdvance = mMaxAdvance; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetSpaceWidth (nscoord &aSpaceCharWidth) -+ { aSpaceCharWidth = mSpaceWidth; -+ return NS_OK; }; -+ -+ NS_IMETHOD GetAveCharWidth (nscoord &aAveCharWidth) -+ { aAveCharWidth = mAveCharWidth; -+ return NS_OK; }; -+ -+ // nsIFontMetricsPS (calls from the font rendering layer) -+ NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength); -+ NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength); -+ -+ NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength, -+ nscoord& aWidth); -+ NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength, -+ nscoord& aWidth); -+ -+ NS_IMETHOD GetTextDimensions(const char* aString, -+ PRUint32 aLength, -+ nsTextDimensions& aDimensions); -+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, -+ PRUint32 aLength, -+ nsTextDimensions& aDimensions, -+ PRInt32* aFontID); -+ NS_IMETHOD GetTextDimensions(const char* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID); -+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions, -+ PRInt32* aFontID); -+ -+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ NS_IMETHOD DrawString(const PRUnichar* aString, PRUint32 aLength, -+ nscoord aX, nscoord aY, -+ PRInt32 aFontID, -+ const nscoord* aSpacing, -+ nsRenderingContextPS *aContext); -+ -+#ifdef MOZ_MATHML -+ NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics); -+ NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString, -+ PRUint32 aLength, -+ nsBoundingMetrics &aBoundingMetrics, -+ PRInt32 *aFontID); -+#endif /* MOZ_MATHML */ -+ -+ NS_IMETHOD SetRightToLeftText(PRBool aIsRTL); -+ -+ NS_IMETHOD GetClusterInfo(const PRUnichar *aText, -+ PRUint32 aLength, -+ PRUint8 *aClusterStarts); -+ -+ virtual PRInt32 GetPosition(const PRUnichar *aText, -+ PRUint32 aLength, -+ nsPoint aPt); -+ -+ NS_IMETHOD GetRangeWidth(const PRUnichar *aText, -+ PRUint32 aLength, -+ PRUint32 aStart, -+ PRUint32 aEnd, -+ PRUint32 &aWidth); -+ -+ NS_IMETHOD GetRangeWidth(const char *aText, -+ PRUint32 aLength, -+ PRUint32 aStart, -+ PRUint32 aEnd, -+ PRUint32 &aWidth); -+ -+ // get hints for the font -+ virtual PRUint32 GetHints (void); -+ -+ // drawing surface methods -+ static nsresult FamilyExists (nsIDeviceContext *aDevice, -+ const nsString &aName); -+ -+ inline nsIDeviceContext *GetDeviceContext() { return mDeviceContext; } -+ -+private: -+ -+ // generic font metrics class bits -+ nsCStringArray mFontList; -+ nsAutoVoidArray mFontIsGeneric; -+ -+ nsIDeviceContext *mDeviceContext; -+ nsCOMPtr<nsIAtom> mLangGroup; -+ nsCString *mGenericFont; -+ float mPointSize; -+ -+ nsCAutoString mDefaultFont; -+ -+ // Pango-related items -+ PangoFontDescription *mPangoFontDesc; -+ PangoContext *mPangoContext; -+ PangoContext *mLTRPangoContext; -+ PangoContext *mRTLPangoContext; -+ PangoAttrList *mPangoAttrList; -+ PRBool mIsRTL; -+ -+ // Cached font metrics -+ nscoord mXHeight; -+ nscoord mSuperscriptOffset; -+ nscoord mSubscriptOffset; -+ nscoord mStrikeoutOffset; -+ nscoord mStrikeoutSize; -+ nscoord mUnderlineOffset; -+ nscoord mUnderlineSize; -+ nscoord mMaxHeight; -+ nscoord mLeading; -+ nscoord mEmHeight; -+ nscoord mEmAscent; -+ nscoord mEmDescent; -+ nscoord mMaxAscent; -+ nscoord mMaxDescent; -+ nscoord mMaxAdvance; -+ nscoord mSpaceWidth; -+ nscoord mPangoSpaceWidth; -+ nscoord mAveCharWidth; -+ -+ // Private methods -+ nsresult RealizeFont(void); -+ nsresult CacheFontMetrics(void); -+ -+ static PRBool EnumFontCallback(const nsString &aFamily, -+ PRBool aIsGeneric, void *aData); -+ -+ void DrawStringSlowly(const gchar *aText, -+ const PRUnichar *aOrigString, -+ PRUint32 aLength, -+ gint aX, gint aY, -+ PangoLayoutLine *aLine, -+ const nscoord *aSpacing, -+ nsRenderingContextPS *aContext); -+ -+ nsresult GetTextDimensionsInternal(const gchar* aString, -+ PRInt32 aLength, -+ PRInt32 aAvailWidth, -+ PRInt32* aBreaks, -+ PRInt32 aNumBreaks, -+ nsTextDimensions& aDimensions, -+ PRInt32& aNumCharsFit, -+ nsTextDimensions& aLastWordDimensions); -+ -+ void FixupSpaceWidths (PangoLayout *aLayout, const char *aString); -+}; -+ -+class nsFontEnumeratorPango : public nsIFontEnumerator -+{ -+public: -+ nsFontEnumeratorPango(); -+ NS_DECL_ISUPPORTS -+ NS_DECL_NSIFONTENUMERATOR -+}; -+ -+#endif -+ -Index: gfx/src/ps/nsPostScriptObj.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.cpp,v -retrieving revision 1.124 -diff -u -p -d -r1.124 nsPostScriptObj.cpp ---- gfx/src/ps/nsPostScriptObj.cpp 26 Jul 2005 15:54:18 -0000 1.124 -+++ gfx/src/ps/nsPostScriptObj.cpp 23 Oct 2006 17:37:29 -0000 -@@ -2061,31 +2061,74 @@ nsPostScriptObj::show(const PRUnichar* t - - #if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) - void --nsPostScriptObj::show(const PRUnichar* aTxt, int aLen, -- const nsAFlatString& aCharList, PRUint16 aSubFontIdx) -+/*nsPostScriptObj::show(const PRUnichar* aTxt, int aLen, -+ const nsAFlatString& aCharList, PRUint16 aSubFontIdx) */ -+nsPostScriptObj::show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset, -+ PRUint16 aSubFontIdx) - { -- int i; -+ PRUint32 i; - fputc('<', mScriptFP); - -- const PRUint16 subFontSize = nsPSFontGenerator::kSubFontSize; -+ for (i = 0; i < aGlyphs->Count(); i++) { -+ PRUint32 glyph = aGlyphs->ValueAt(i); -+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph)); -+ } - -- // the character repertoire of a subfont (255 characters max) -- const nsAString& repertoire = -- Substring(aCharList, aSubFontIdx * subFontSize, -- PR_MIN(subFontSize, -- aCharList.Length() - aSubFontIdx * subFontSize)); -+ fputs("> show\n", mScriptFP); -+} -+#endif - -- for (i = 0; i < aLen; i++) { -- // XXX This is a little inefficient, but printing is not perf. critical. -- NS_ASSERTION(repertoire.FindChar(aTxt[i]) != kNotFound, -- "character is not covered by this subfont"); -- -- // Type 1 encoding vector has 256 slots, but the 0-th slot is -- // reserved for /.notdef so that we use the 1st through 255th slots -- // for actual characters (hence '+ 1') -- fprintf(mScriptFP, "%02x", repertoire.FindChar(aTxt[i]) + 1); -+#ifdef MOZ_ENABLE_PANGO -+void -+nsPostScriptObj::show(const PangoGlyphString *glyphs, float zoom, -+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx) -+{ -+ PRUint32 i; -+ int horiz = 1; -+ -+ if (glyphs->glyphs[0].geometry.x_offset || glyphs->glyphs[0].geometry.y_offset) -+ rmoveto (NSToCoordRound (zoom * glyphs->glyphs[0].geometry.x_offset / PANGO_SCALE), -+ NSToCoordRound (zoom * glyphs->glyphs[0].geometry.y_offset / PANGO_SCALE)); -+ -+ fputc('<', mScriptFP); -+ -+ for (i = 0; i < glyphs->num_glyphs; i++) { -+ PRUint32 glyph = glyphs->glyphs[i].glyph; -+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph)); -+ if (glyphs->glyphs[i].geometry.y_offset) -+ horiz = 0; -+ } -+ -+ if (horiz) { -+ fputs(">\n[", mScriptFP); -+ for (i = 1; i < glyphs->num_glyphs; i++) { -+ fprintf(mScriptFP, "%d ", -+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.x_offset -+ + glyphs->glyphs[i-1].geometry.width -+ - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE)); -+ } -+ fprintf(mScriptFP, "%d", -+ NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width -+ - glyphs->glyphs[i-1].geometry.x_offset -+ - glyphs->glyphs[ 0].geometry.x_offset) / PANGO_SCALE)); -+ fputs("] xshow\n", mScriptFP); -+ } else { -+ fputs(">\n[", mScriptFP); -+ for (i = 1; i < glyphs->num_glyphs; i++) { -+ fprintf(mScriptFP, "%d %d ", -+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.x_offset -+ + glyphs->glyphs[i-1].geometry.width -+ - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE), -+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.y_offset -+ - glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE)); -+ } -+ fprintf(mScriptFP, "%d %d", -+ NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width -+ - glyphs->glyphs[i-1].geometry.x_offset -+ - glyphs->glyphs[ 0].geometry.x_offset) / PANGO_SCALE), -+ NSToCoordRound (zoom * (- glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE)); -+ fputs("] xyshow\n", mScriptFP); - } -- fputs("> show\n", mScriptFP); - } - #endif - -@@ -2101,6 +2144,16 @@ nsPostScriptObj::moveto(nscoord x, nscoo - - /** --------------------------------------------------- - * See documentation in nsPostScriptObj.h -+ * @update 10/20/06 behdad -+ */ -+void -+nsPostScriptObj::rmoveto(nscoord x, nscoord y) -+{ -+ fprintf(mScriptFP, "%d %d rmoveto\n", x, y); -+} -+ -+/** --------------------------------------------------- -+ * See documentation in nsPostScriptObj.h - * @update 2/1/99 dwc - */ - void -Index: gfx/src/ps/nsPostScriptObj.h -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.h,v -retrieving revision 1.47 -diff -u -p -d -r1.47 nsPostScriptObj.h ---- gfx/src/ps/nsPostScriptObj.h 8 May 2005 15:01:20 -0000 1.47 -+++ gfx/src/ps/nsPostScriptObj.h 23 Oct 2006 17:37:30 -0000 -@@ -57,9 +57,15 @@ - #include "nsIPersistentProperties2.h" - #include "nsTempfilePS.h" - #include "nsEPSObjectPS.h" -+#ifdef MOZ_ENABLE_PANGO -+#include <pango/pango.h> -+#endif -+ - -+class nsPSFontGenerator; - class nsIImage; - class nsIAtom; -+class nsValueArray; - #endif - - #include <stdio.h> -@@ -217,6 +223,14 @@ public: - */ - void moveto(nscoord aX, nscoord aY); - /** --------------------------------------------------- -+ * Move relative to the current point -+ * @update 10/20/2006 behdad -+ * @param aX X coordinate -+ * aY Y coordinate -+ * @return VOID -+ */ -+ void rmoveto(nscoord aX, nscoord aY); -+ /** --------------------------------------------------- - * Add a line to the current path, from the current point - * to the specified point. - * @update 9/30/2003 -@@ -346,12 +360,24 @@ public: - */ - void show(const PRUnichar* aText, int aLen, const char *aAlign, int aType); - /** --------------------------------------------------- -- * This version takes a PRUnichar string, a font subset string -- * for freetype printing and a subfont index -+ * This version of show takes an array of glyphs, subfont and subfont index -+ * to render and is used for freetype and xft printing. - * @update 2/15/2005 jshin@mailaps.org -+ * @update 6/7/2005 blizzard@mozilla.org - */ -- void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList, -+ void show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset, - PRUint16 aSubFontIdx); -+ /*void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList, -+ PRUint16 aSubFontIdx); */ -+#ifdef MOZ_ENABLE_PANGO -+ /** --------------------------------------------------- -+ * This version of show takes a pango glyph string, subfont and subfont index -+ * to render and is used for pango printing. -+ * @update 10/20/2006 behdad@behdad.org -+ */ -+ void show(const PangoGlyphString *glyphs, float zoom, -+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx); -+#endif - /** --------------------------------------------------- - * set the clipping path to the current path using the winding rule - * @update 2/1/99 dwc -Index: gfx/src/ps/nsRenderingContextPS.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.cpp,v -retrieving revision 1.83 -diff -u -p -d -r1.83 nsRenderingContextPS.cpp ---- gfx/src/ps/nsRenderingContextPS.cpp 4 Mar 2005 07:39:27 -0000 1.83 -+++ gfx/src/ps/nsRenderingContextPS.cpp 23 Oct 2006 17:37:31 -0000 -@@ -251,6 +251,8 @@ nsRenderingContextPS :: GetDrawingSurfac - NS_IMETHODIMP - nsRenderingContextPS :: GetHints(PRUint32& aResult) - { -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ aResult = metrics->GetHints (); - return NS_OK; - } - -@@ -1006,8 +1008,11 @@ nsRenderingContextPS::GetTextDimensions( - nsTextDimensions& aLastWordDimensions, - PRInt32* aFontID) - { -- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions"); -- return NS_ERROR_NOT_IMPLEMENTED; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks, -+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID); - } - - NS_IMETHODIMP -@@ -1021,43 +1026,31 @@ nsRenderingContextPS::GetTextDimensions( - nsTextDimensions& aLastWordDimensions, - PRInt32* aFontID) - { -- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions"); -- return NS_ERROR_NOT_IMPLEMENTED; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks, -+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID); - } - - NS_IMETHODIMP - nsRenderingContextPS :: GetTextDimensions(const char* aString, PRUint32 aLength, - nsTextDimensions& aDimensions) - { -- nsresult rv = NS_ERROR_FAILURE; -- -- if (mFontMetrics) { -- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -- metrics->GetStringWidth(aString, aDimensions.width, aLength); -- metrics->GetMaxAscent(aDimensions.ascent); -- metrics->GetMaxDescent(aDimensions.descent); -- rv = NS_OK; -- } -- -- return rv; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetTextDimensions (aString, aLength, aDimensions); - } - - NS_IMETHODIMP - nsRenderingContextPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, - nsTextDimensions& aDimensions, PRInt32* aFontID) - { -- nsresult rv = NS_ERROR_FAILURE; -- -- if (mFontMetrics) { -- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -- metrics->GetStringWidth(aString, aDimensions.width, aLength); -- //XXX temporary - bug 96609 -- metrics->GetMaxAscent(aDimensions.ascent); -- metrics->GetMaxDescent(aDimensions.descent); -- rv = NS_OK; -- } -- -- return rv; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetTextDimensions (aString, aLength, aDimensions, aFontID); - } - - /** --------------------------------------------------- -@@ -1073,47 +1066,7 @@ nsRenderingContextPS :: DrawString(const - - nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); - NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -- -- // When FT2 printing is enabled, we don't need to set langgroup --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) { --#endif -- nsCOMPtr<nsIAtom> langGroup; -- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup)); -- mPSObj->setlanggroup(langGroup); --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -- } --#endif -- -- if (aLength == 0) -- return NS_OK; -- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics); -- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); -- fontPS->SetupFont(this); -- -- PRUint32 i, start = 0; -- for (i=0; i<aLength; i++) { -- nsFontPS* fontThisChar; -- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics); -- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); -- if (fontThisChar != fontPS) { -- // draw text up to this point -- aX += DrawString(aString+start, i-start, aX, aY, fontPS, -- aSpacing?aSpacing+start:nsnull); -- start = i; -- -- // setup for following text -- fontPS = fontThisChar; -- fontPS->SetupFont(this); -- } -- } -- -- // draw the last part -- if (aLength-start) -- DrawString(aString+start, aLength-start, aX, aY, fontPS, -- aSpacing?aSpacing+start:nsnull); -- -- return NS_OK; -+ return metrics->DrawString (aString, aLength, aX, aY, aSpacing, this); - } - - /** --------------------------------------------------- -@@ -1129,110 +1082,7 @@ nsRenderingContextPS :: DrawString(const - - nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); - NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -- --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -- // When FT2 printing is enabled, we don't need to set langgroup -- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) { --#endif -- nsCOMPtr<nsIAtom> langGroup = nsnull; -- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup)); -- mPSObj->setlanggroup(langGroup); --#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) -- } --#endif -- -- /* build up conversion table */ -- mPSObj->preshow(aString, aLength); -- -- if (aLength == 0) -- return NS_OK; -- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics); -- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); -- fontPS->SetupFont(this); -- -- PRUint32 i, start = 0; -- for (i=0; i<aLength; i++) { -- nsFontPS* fontThisChar; -- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics); -- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); -- if (fontThisChar != fontPS) { -- // draw text up to this point -- aX += DrawString(aString+start, i-start, aX, aY, fontPS, -- aSpacing?aSpacing+start:nsnull); -- start = i; -- -- // setup for following text -- fontPS = fontThisChar; -- fontPS->SetupFont(this); -- } -- } -- -- // draw the last part -- if (aLength-start) -- DrawString(aString+start, aLength-start, aX, aY, fontPS, -- aSpacing?aSpacing+start:nsnull); -- -- return NS_OK; --} -- --PRInt32 --nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength, -- nscoord &aX, nscoord &aY, nsFontPS* aFontPS, -- const nscoord* aSpacing) --{ -- nscoord width = 0; -- PRInt32 x = aX; -- PRInt32 y = aY; -- -- PRInt32 dxMem[500]; -- PRInt32* dx0 = 0; -- if (aSpacing) { -- dx0 = dxMem; -- if (aLength > 500) { -- dx0 = new PRInt32[aLength]; -- NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY); -- } -- mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0); -- } -- -- mTranMatrix->TransformCoord(&x, &y); -- width = aFontPS->DrawString(this, x, y, aString, aLength); -- -- if ((aSpacing) && (dx0 != dxMem)) { -- delete [] dx0; -- } -- -- return width; --} -- -- --PRInt32 --nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength, -- nscoord aX, nscoord aY, nsFontPS* aFontPS, -- const nscoord* aSpacing) --{ -- nscoord width = 0; -- PRInt32 x = aX; -- PRInt32 y = aY; -- -- if (aSpacing) { -- // Slow, but accurate rendering -- const PRUnichar* end = aString + aLength; -- while (aString < end){ -- x = aX; -- y = aY; -- mTranMatrix->TransformCoord(&x, &y); -- aFontPS->DrawString(this, x, y, aString, 1); -- aX += *aSpacing++; -- aString++; -- } -- width = aX; -- } else { -- mTranMatrix->TransformCoord(&x, &y); -- width = aFontPS->DrawString(this, x, y, aString, aLength); -- } -- -- return width; -+ return metrics->DrawString (aString, aLength, aX, aY, aFontID, aSpacing, this); - } - - /** --------------------------------------------------- -@@ -1346,8 +1196,10 @@ nsRenderingContextPS::GetBoundingMetrics - PRUint32 aLength, - nsBoundingMetrics& aBoundingMetrics) - { -- // Fill me up -- return NS_ERROR_NOT_IMPLEMENTED; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics); - } - - /** -@@ -1359,8 +1211,10 @@ nsRenderingContextPS::GetBoundingMetrics - nsBoundingMetrics& aBoundingMetrics, - PRInt32* aFontID) - { -- // Fill me up -- return NS_ERROR_NOT_IMPLEMENTED; -+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); -+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); -+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); -+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics, aFontID); - } - #endif /* MOZ_MATHML */ - -Index: gfx/src/ps/nsRenderingContextPS.h -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.h,v -retrieving revision 1.49 -diff -u -p -d -r1.49 nsRenderingContextPS.h ---- gfx/src/ps/nsRenderingContextPS.h 20 Sep 2004 06:46:16 -0000 1.49 -+++ gfx/src/ps/nsRenderingContextPS.h 23 Oct 2006 17:37:35 -0000 -@@ -154,6 +154,10 @@ public: - NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength, - nscoord& aWidth, PRInt32 *aFontID); - -+ nsTransform2D *GetTranMatrix() { -+ return mTranMatrix; -+ } -+ - NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, - nscoord aX, nscoord aY, - const nscoord* aSpacing); -@@ -164,13 +168,6 @@ public: - NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY, - PRInt32 aFontID, - const nscoord* aSpacing); --protected: -- PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength, -- nscoord aX, nscoord aY, nsFontPS* aFontPS, -- const nscoord* aSpacing); -- PRInt32 DrawString(const char *aString, PRUint32 aLength, -- nscoord &aX, nscoord &aY, nsFontPS* aFontPS, -- const nscoord* aSpacing); - public: - - NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength, -Index: gfx/src/ps/nsType1.cpp -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.cpp,v -retrieving revision 1.5.8.1 -diff -u -p -d -r1.5.8.1 nsType1.cpp ---- gfx/src/ps/nsType1.cpp 19 Oct 2005 08:16:22 -0000 1.5.8.1 -+++ gfx/src/ps/nsType1.cpp 23 Oct 2006 17:37:39 -0000 -@@ -73,8 +73,13 @@ - #include "nsIFreeType2.h" - #include "nsServiceManagerUtils.h" - #endif -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) -+#include FT_TYPE1_TABLES_H -+#endif - #include "nsPrintfCString.h" - #include "nsAutoBuffer.h" -+#include "nsValueArray.h" -+#include "nsVoidArray.h" - - #define HEXASCII_LINE_LEN 64 - -@@ -113,7 +118,7 @@ static void encryptAndHexOut(FILE *aFile - const char *aBuf, PRInt32 aLen = -1); - static void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey, - const char *aStr, PRUint32 aLen, -- PRUnichar aId); -+ const char *aGlyphName); - static void flattenName(nsCString& aString); - - /* thunk a short name for this function */ -@@ -202,19 +207,30 @@ Type1EncryptString(unsigned char *aInBuf - aOutBuf[i] = Type1Encrypt(aInBuf[i], &key); - } - -+static FT_UShort -+get_upm (FT_Face face) -+{ -+ FT_UShort upm = face->units_per_EM; -+ -+ if (!upm) -+ upm = 1000; // bitmap font or something -+ -+ return upm; -+} -+ - static PRBool - sideWidthAndBearing(const FT_Vector *aEndPt, FT2PT1_info *aFti) - { - int aw = 0; - int ah = 0; -- FT_UShort upm = aFti->face->units_per_EM; -+ FT_UShort upm = get_upm (aFti->face); - FT_GlyphSlot slot; - FT_Glyph glyph; - FT_BBox bbox; - - slot = aFti->face->glyph; - --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - FT_Error error = FT_Get_Glyph(slot, &glyph); - if (error) { - NS_ERROR("sideWidthAndBearing failed to get glyph"); -@@ -256,7 +272,7 @@ static int - moveto(nsFT_CONST FT_Vector *aEndPt, void *aClosure) - { - FT2PT1_info *fti = (FT2PT1_info *)aClosure; -- FT_UShort upm = fti->face->units_per_EM; -+ FT_UShort upm = get_upm (fti->face); - PRBool rslt; - - if (fti->elm_cnt == 0) { -@@ -293,7 +309,7 @@ static int - lineto(nsFT_CONST FT_Vector *aEndPt, void *aClosure) - { - FT2PT1_info *fti = (FT2PT1_info *)aClosure; -- FT_UShort upm = fti->face->units_per_EM; -+ FT_UShort upm = get_upm (fti->face); - - if (toCS(upm, aEndPt->x) == fti->cur_x) { - fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y); -@@ -320,7 +336,7 @@ conicto(nsFT_CONST FT_Vector *aControlPt - void *aClosure) - { - FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure; -- FT_UShort upm = ftinfo->face->units_per_EM; -+ FT_UShort upm = get_upm (ftinfo->face); - double ctl_x, ctl_y; - double cur_x, cur_y, x3, y3; - FT_Vector aControlPt1, aControlPt2; -@@ -353,7 +369,7 @@ cubicto(nsFT_CONST FT_Vector *aControlPt - nsFT_CONST FT_Vector *aEndPt, void *aClosure) - { - FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure; -- FT_UShort upm = ftinfo->face->units_per_EM; -+ FT_UShort upm = get_upm (ftinfo->face); - double cur_x, cur_y, x1, y1, x2, y2, x3, y3; - - cur_x = ftinfo->cur_x; -@@ -408,8 +424,55 @@ static FT_Outline_Funcs ft_outline_funcs - 0 - }; - -+ -+static int -+trace_bitmap_glyph (FT_GlyphSlot slot, FT2PT1_info *fti) -+{ -+ unsigned char *row, *byte_ptr, byte; -+ int rows, cols; -+ int x, y, bit_mask; -+ int upm, x_off, y_off, x_mult, y_mult; -+ -+ upm = get_upm (slot->face); -+ x_off = slot->bitmap_left; -+ y_off = slot->bitmap_top; -+ x_mult = upm / slot->face->size->metrics.x_ppem; -+ y_mult = upm / slot->face->size->metrics.y_ppem; -+ -+ switch (slot->bitmap.pixel_mode) { -+ case FT_PIXEL_MODE_MONO: -+ -+ for (y = 0, row = slot->bitmap.buffer, rows = slot->bitmap.rows; rows; row += slot->bitmap.pitch, rows--, y++) { -+ for (x = 0, byte_ptr = row, cols = (slot->bitmap.width + 7) / 8; cols; byte_ptr++, cols--) { -+ byte = *byte_ptr; -+ for (bit_mask = 128; bit_mask && x < slot->bitmap.width; bit_mask >>= 1, x++) { -+ if (byte & bit_mask) { -+ FT_Vector p; -+ p.x = x_mult * (x_off + x); -+ p.y = y_mult * (y_off - y); -+ moveto(&p, (void *) fti); -+ p.x += x_mult; -+ lineto(&p, (void *) fti); -+ p.y += y_mult; -+ lineto(&p, (void *) fti); -+ p.x -= x_mult; -+ lineto(&p, (void *) fti); -+ } -+ } -+ } -+ } -+ break; -+ -+ default: -+ return 1; -+ } -+ -+ return 0; -+} -+ -+ - FT_Error --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - FT2GlyphToType1CharString(FT_Face aFace, PRUint32 aGlyphID, - int aWmode, int aLenIV, unsigned char *aBuf) - #else -@@ -423,7 +486,7 @@ FT2GlyphToType1CharString(nsIFreeType2 * - unsigned char *start = aBuf; - FT2PT1_info fti; - --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - FT_Error error = FT_Load_Glyph(aFace, aGlyphID, flags); - if (error) { - NS_ERROR("failed to load aGlyphID"); -@@ -438,11 +501,6 @@ FT2GlyphToType1CharString(nsIFreeType2 * - #endif - slot = aFace->glyph; - -- if (slot->format != ft_glyph_format_outline) { -- NS_ERROR("aGlyphID is not an outline glyph"); -- return 1; -- } -- - #ifdef MOZ_ENABLE_FREETYPE2 - fti.ft2 = aFt2; - #endif -@@ -456,18 +514,27 @@ FT2GlyphToType1CharString(nsIFreeType2 * - for (j=0; j< aLenIV; j++) { - fti.len += ecsi(&fti.buf, 0); - } --#ifdef MOZ_ENABLE_XFT -- if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) { -- NS_ERROR("error decomposing aGlyphID"); -- return 1; -- } -+ -+ if (slot->format == ft_glyph_format_outline) { -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) -+ if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) { -+ NS_ERROR("error decomposing aGlyphID"); -+ return 1; -+ } - #else -- rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti); -- if (NS_FAILED(rv)) { -- NS_ERROR("error decomposing aGlyphID"); -- return 1; -- } -+ rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti); -+ if (NS_FAILED(rv)) { -+ NS_ERROR("error decomposing aGlyphID"); -+ } - #endif -+ } else if (slot->format == ft_glyph_format_bitmap) { -+ /* ok, it's a bitmap glyph. trace it! */ -+ if (trace_bitmap_glyph (slot, &fti)) { -+ NS_ERROR("error tracing bitmap glyph"); -+ } -+ } else { -+ NS_ERROR("aGlyphID has unhandled format"); -+ } - - if (fti.elm_cnt) { - fti.len += csc(&fti.buf, T1_CLOSEPATH); -@@ -491,28 +558,52 @@ FT2GlyphToType1CharString(nsIFreeType2 * - } - - static PRBool --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - outputType1SubFont(FT_Face aFace, - #else - outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace, - #endif -- const nsAString &aCharIDs, const char *aFontName, -- int aWmode, int aLenIV, FILE *aFile); -+ nsValueArray *aGlyphs, -+ PRUint32 aOffset, PRUint32 aLen, -+ const char *aFontName, -+ int aWmode, int aLenIV, FILE *aFile); - - nsresult - FT2ToType1FontName(FT_Face aFace, int aWmode, nsCString& aFontName) - { -+ // only hash the first 10 000 bytes of the font -+ int size = aFace->stream->size; -+ size = size > 10000 ? 10000 : size; -+ -+ unsigned char *data; -+ if (aFace->stream->read) { -+ data = (unsigned char *) malloc (size); -+ aFace->stream->read (aFace->stream, 0, data, size); -+ } else { -+ data = aFace->stream->base; -+ } -+ -+ unsigned int data_hash = 0; -+ int i; -+ for (i = 0; i < size; i++) -+ data_hash = (data_hash << 5) - data_hash + data[size]; -+ -+ if (aFace->stream->read) -+ free (data); -+ - aFontName = aFace->family_name; - aFontName.AppendLiteral("."); - aFontName += aFace->style_name; -- aFontName += nsPrintfCString(".%ld.%d", aFace->face_index, aWmode ? 1 : 0); -+ aFontName += nsPrintfCString(".%ld.%d.%lx.%x", aFace->face_index, aWmode ? 1 : 0, -+ (long) aFace->stream->size, data_hash); - flattenName(aFontName); -+ - return NS_OK; - } - - // output a subsetted truetype font converted to multiple type 1 fonts - PRBool --FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset, -+FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset, - int aWmode, FILE *aFile) - { - #ifdef MOZ_ENABLE_FREETYPE2 -@@ -527,32 +618,35 @@ FT2SubsetToType1FontSet(FT_Face aFace, c - nsCAutoString fontNameBase; - FT2ToType1FontName(aFace, aWmode, fontNameBase); - PRUint32 i = 0; -- for (; i <= aSubset.Length() / 255 ; i++) { -+ for (; i <= aGlyphSubset->Count() / 255 ; i++) { - nsCAutoString fontName(fontNameBase); - fontName.AppendLiteral(".Set"); - fontName.AppendInt(i); --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - outputType1SubFont(aFace, - #else - outputType1SubFont(ft2, aFace, - #endif -- Substring(aSubset, i * 255, PR_MIN(255, aSubset.Length() - i * 255)), -- fontName.get(), aWmode, 4, aFile); -+ aGlyphSubset, -+ (i * 255), PR_MIN(255, aGlyphSubset->Count() - i * 255), -+ fontName.get(), aWmode, 4, aFile); - } - return PR_TRUE; - } - - // output a type 1 font (with 255 characters or fewer) - static PRBool --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - outputType1SubFont(FT_Face aFace, - #else - outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace, - #endif -- const nsAString& aCharIDs, const char *aFontName, -- int aWmode, int aLenIV, FILE *aFile) -+ nsValueArray *aGlyphs, -+ PRUint32 aOffset, PRUint32 aLen, -+ const char *aFontName, -+ int aWmode, int aLenIV, FILE *aFile) - { -- FT_UShort upm = aFace->units_per_EM; -+ FT_UShort upm = get_upm (aFace); - - fprintf(aFile, "%%%%BeginResource: font %s\n" - "%%!PS-AdobeFont-1.0-3.0 %s 1.0\n" -@@ -573,9 +667,13 @@ outputType1SubFont(nsIFreeType2 *aFt2, F - toCS(upm, aFace->bbox.xMax), - toCS(upm, aFace->bbox.yMax)); - -- nsString charIDstr(aCharIDs); -- PRUint32 len = aCharIDs.Length(); -- -+ nsValueArray glyphs(PR_UINT16_MAX); -+ nsCStringArray glyphnames(PR_UINT16_MAX); -+ glyphs = *aGlyphs; -+ -+ PRUint32 len = aLen; -+ PRUint32 i; -+ - if (len < 10) { - // Add a small set of characters to the subset of the user - // defined font to produce to make sure the font ends up -@@ -584,25 +682,47 @@ outputType1SubFont(nsIFreeType2 *aFt2, F - // XXX : need to check if this is true of type 1 fonts as well. - // I suspect it's only the case of CID-keyed fonts (type 9) we used to - // generate. -- charIDstr.AppendLiteral("1234567890"); -+ for (i = 1; i <= 10; i++) { -+ glyphs.AppendValue(i); -+ } - len += 10; - } - -- const PRUnichar *charIDs = charIDstr.get(); -- -- PRUint32 i; -+ FT_Int has_glyph_name; -+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO) -+ has_glyph_name = FT_Has_PS_Glyph_Names(aFace); -+#else -+ has_glyph_name = aFt2->hasPSGlyphNames(aFace); -+#endif - - // construct an Encoding vector : the 0th element - // is /.notdef -- fputs("/Encoding [\n/.notdef\n", aFile); -- for (i = 0; i < len; ++i) { -- fprintf(aFile, "/uni%04X", charIDs[i]); -- if (i % 8 == 7) fputc('\n', aFile); -+ fputs("/Encoding [\n/.notdef", aFile); -+ for (i = aOffset; i < aOffset + aLen; ++i) { -+ nsCString name; -+ char buffer[256]; -+ -+ if (glyphs.ValueAt(i) == 0) { -+ name = "/.notdef"; -+ } else if (!has_glyph_name || -+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO) -+ FT_Get_Glyph_Name(aFace, glyphs.ValueAt(i), buffer, 255) != FT_Err_Ok -+#else -+ NS_FAILED(aFt2->getGlyphName(aFace, glyphs.ValueAt(i), buffer, 255)) -+#endif -+ ) { -+ name = nsPrintfCString(256, "/idx%04X", glyphs.ValueAt(i)); -+ } else { -+ name = nsPrintfCString(256, "/%s", buffer); -+ } -+ glyphnames.AppendCString(name); -+ fprintf(aFile, name.get()); -+ if ((i-aOffset) % 8 == 6) fputc('\n', aFile); - } - -- for (i = len; i < 255; ++i) { -+ for (i = PR_MAX (0, 255 - int(aLen)); i; --i) { - fputs("/.notdef", aFile); -- if (i % 8 == 7) fputc('\n', aFile); -+ if (i % 8 == 1) fputc('\n', aFile); - } - fputs("] def\n", aFile); - -@@ -630,23 +750,21 @@ outputType1SubFont(nsIFreeType2 *aFt2, F - // get the maximum charstring length without actually filling up the buffer - PRInt32 charStringLen; - PRInt32 maxCharStringLen = --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, nsnull); - #else - FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, nsnull); - #endif - -- PRUint32 glyphID; -- -- for (i = 0; i < len; i++) { --#ifdef MOZ_ENABLE_XFT -- glyphID = FT_Get_Char_Index(aFace, charIDs[i]); -+ for (i = aOffset; i < aOffset + aLen; i++) { -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - charStringLen = -- FT2GlyphToType1CharString(aFace, glyphID, aWmode, aLenIV, nsnull); -+ FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, aLenIV, -+ nsnull); - #else -- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID); - charStringLen = -- FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, aLenIV, nsnull); -+ FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), aWmode, aLenIV, -+ nsnull); - #endif - - if (charStringLen > maxCharStringLen) -@@ -666,7 +784,7 @@ outputType1SubFont(nsIFreeType2 *aFt2, F - len + 1).get()); - - // output the notdef glyph --#ifdef MOZ_ENABLE_XFT -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) - charStringLen = FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, - charString.get()); - #else -@@ -676,22 +794,20 @@ outputType1SubFont(nsIFreeType2 *aFt2, F - - // enclose charString with "/.notdef RD ..... ND" - charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()), -- charStringLen, 0); -+ charStringLen, "/.notdef"); - - - // output the charstrings for each glyph in this sub font -- for (i = 0; i < len; i++) { --#ifdef MOZ_ENABLE_XFT -- glyphID = FT_Get_Char_Index(aFace, charIDs[i]); -- charStringLen = FT2GlyphToType1CharString(aFace, glyphID, aWmode, -+ for (i = aOffset; i < aOffset + aLen; i++) { -+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) -+ charStringLen = FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, - aLenIV, charString.get()); - #else -- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID); -- charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, -- aLenIV, charString.get()); -+ charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), -+ aWmode, aLenIV, charString.get()); - #endif - charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()), -- charStringLen, charIDs[i]); -+ charStringLen, glyphnames.CStringAt(i - aOffset)->get()); - } - - // wrap up the encrypted part of the font definition -@@ -753,15 +869,12 @@ void encryptAndHexOut(FILE *aFile, PRUin - - /* static */ - void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey, -- const char *aStr, PRUint32 aLen, PRUnichar aId) -+ const char *aStr, PRUint32 aLen, const char *aGlyphName) - { - // use a local buffer instead of nsPrintfCString to avoid alloc. - char buf[30]; - int oLen; -- if (aId == 0) -- oLen = PR_snprintf(buf, 30, "/.notdef %d RD ", aLen); -- else -- oLen = PR_snprintf(buf, 30, "/uni%04X %d RD ", aId, aLen); -+ oLen = PR_snprintf(buf, 30, "%s %d RD ", aGlyphName, aLen); - - if (oLen >= 30) { - NS_WARNING("buffer size exceeded. charstring will be truncated"); -Index: gfx/src/ps/nsType1.h -=================================================================== -RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.h,v -retrieving revision 1.5 -diff -u -p -d -r1.5 nsType1.h ---- gfx/src/ps/nsType1.h 4 Mar 2005 07:39:27 -0000 1.5 -+++ gfx/src/ps/nsType1.h 23 Oct 2006 17:37:39 -0000 -@@ -122,8 +122,9 @@ FT_Error FT2GlyphToType1CharString(nsIFr - - class nsString; - class nsCString; -+class nsValueArray; - --PRBool FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset, -+PRBool FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset, - int aWmode, FILE *aFile); - nsresult FT2ToType1FontName(FT_Face aFace, int aWmode, - nsCString& aFontName); -Index: config/system-headers -=================================================================== ---- config/system-headers 2006-10-26 12:21:39.000000000 -0400 -+++ config/system-headers 2006-10-26 12:23:29.000000000 -0400 -@@ -199,6 +199,7 @@ - freetype/ftoutln.h - freetype/ttnameid.h - freetype/tttables.h -+freetype/t1tables.h - fribidi/fribidi.h - FSp_fopen.h - fstream.h -@@ -501,6 +503,7 @@ - pango/pangofc-fontmap.h - pango/pango-fontmap.h - pango/pango.h -+pango/pangoft2.h - pango/pangoxft.h - pango/pangox.h - pango-types.h - |