]> git.pld-linux.org Git - packages/firefox.git/blame - mozilla-firefox-pango-printing.patch
- updated to 3.5rc3
[packages/firefox.git] / mozilla-firefox-pango-printing.patch
CommitLineData
e36ee87a 1Patch for Firefox 1.5.0.7 to add support for printing via Pango.
2This also implements printing MathML via Pango, and prints bitmap
3fonts too.
4
5Authors:
6 Behdad Esfahbod
7 Chris Blizzard
8 Akira TAGOH
9
10Index: gfx/src/freetype/nsFreeType.cpp
11===================================================================
12RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.cpp,v
13retrieving revision 1.28
14diff -u -p -d -r1.28 nsFreeType.cpp
15--- gfx/src/freetype/nsFreeType.cpp 13 Jul 2005 18:21:10 -0000 1.28
16+++ gfx/src/freetype/nsFreeType.cpp 23 Oct 2006 17:37:09 -0000
17@@ -123,6 +123,8 @@ FtFuncList nsFreeType2::FtFuncs [] = {
18 // #endif
19 {"FT_Get_First_Char", NS_FT2_OFFSET(nsFT_Get_First_Char), PR_FALSE},
20 {"FT_Get_Next_Char", NS_FT2_OFFSET(nsFT_Get_Next_Char), PR_FALSE},
21+ {"FT_Has_PS_Glyph_Names", NS_FT2_OFFSET(nsFT_Has_PS_Glyph_Names), PR_FALSE},
22+ {"FT_Get_Glyph_Name", NS_FT2_OFFSET(nsFT_Get_Glyph_Name), PR_TRUE},
23 {nsnull, 0, 0}
24 };
25
26@@ -388,6 +390,22 @@ nsFreeType2::GetNextChar(FT_Face face, F
27 }
28
29 NS_IMETHODIMP
30+nsFreeType2::HasPSGlyphNames(FT_Face face, FT_Int *result)
31+{
32+ // call the FreeType2 function via the function pointer
33+ *result = nsFT_Has_PS_Glyph_Names(face);
34+ return NS_OK;
35+}
36+
37+NS_IMETHODIMP
38+nsFreeType2::GetGlyphName(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max)
39+{
40+ // call the FreeType2 function via the function pointer
41+ FT_Error error = nsFT_Get_Glyph_Name(face, glyph_index, buffer, buffer_max);
42+ return error ? NS_ERROR_FAILURE : NS_OK;
43+}
44+
45+NS_IMETHODIMP
46 nsFreeType2::SupportsExtFunc(PRBool *res)
47 {
48 *res = gHasExtFunc;
49Index: gfx/src/freetype/nsFreeType.h
50===================================================================
51RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.h,v
52retrieving revision 1.18
53diff -u -p -d -r1.18 nsFreeType.h
54--- gfx/src/freetype/nsFreeType.h 1 May 2005 17:36:19 -0000 1.18
55+++ gfx/src/freetype/nsFreeType.h 23 Oct 2006 17:37:09 -0000
56@@ -52,6 +52,7 @@
57 #include FT_CACHE_H
58 #include FT_CACHE_IMAGE_H
59 #include FT_TRUETYPE_TABLES_H
60+#include FT_TYPE1_TABLES_H
61 #include "nsIFreeType2.h"
62
63 typedef struct FT_FaceRec_* FT_Face;
64@@ -138,6 +139,8 @@ typedef FT_Error (*FT_Glyph_To_Bitmap_t)
65
66 typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face, FT_UInt*);
67 typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face, FT_ULong, FT_UInt*);
68+typedef FT_Int (*FT_Has_PS_Glyph_Names_t)(FT_Face);
69+typedef FT_Error (*FT_Get_Glyph_Name_t)(FT_Face, FT_UInt, FT_Pointer, FT_UInt);
70
71 class nsFreeTypeFace;
72
73@@ -193,11 +196,13 @@ protected:
74 // #endif
75 FT_Get_First_Char_t nsFT_Get_First_Char;
76 FT_Get_Next_Char_t nsFT_Get_Next_Char;
77+ FT_Has_PS_Glyph_Names_t nsFT_Has_PS_Glyph_Names;
78+ FT_Get_Glyph_Name_t nsFT_Get_Glyph_Name;
79
80 // this array needs to be big enough to hold all the function pointers
81 // plus one extra for the null at the end
82 // #ifdef MOZ_SVG
83- static FtFuncList FtFuncs[24];
84+ static FtFuncList FtFuncs[28];
85 // #else
86 // static FtFuncList FtFuncs[20];
87 // #endif
88Index: gfx/src/ps/Makefile.in
89===================================================================
90RCS file: /cvsroot/mozilla/gfx/src/ps/Makefile.in,v
91retrieving revision 1.57.8.1
92diff -d -u -p -r1.57.8.1 Makefile.in
93--- gfx/src/ps/Makefile.in 17 Jun 2006 15:16:14 -0000 1.57.8.1
94+++ gfx/src/ps/Makefile.in 24 Oct 2006 18:36:45 -0000
95@@ -98,6 +98,15 @@ EXTRA_DSO_LDOPTS = \
96 $(MOZ_UNICHARUTIL_LIBS) \
97 $(NULL)
98
99+ifdef MOZ_ENABLE_PANGO
100+CPPSRCS += \
101+ nsFontMetricsPSPango.cpp \
102+ mozilla-ps-decoder.cpp
103+EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS)
104+CXXFLAGS += $(MOZ_PANGO_CFLAGS)
105+CFLAGS += $(MOZ_PANGO_CFLAGS)
106+endif
107+
108 ifdef MOZ_ENABLE_XFT
109 EXTRA_DSO_LDOPTS += \
110 $(MOZ_XFT_LIBS) \
111@@ -105,7 +114,7 @@ EXTRA_DSO_LDOPTS += \
112 $(NULL)
113 endif
114
115-ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT))
116+ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)$(MOZ_ENABLE_PANGO))
117 CPPSRCS += \
118 nsType1.cpp \
119 $(NULL)
120Index: gfx/src/ps/mozilla-ps-decoder.cpp
121===================================================================
122RCS file: gfx/src/ps/mozilla-ps-decoder.cpp
123diff -N gfx/src/ps/mozilla-ps-decoder.cpp
124--- /dev/null 1 Jan 1970 00:00:00 -0000
125+++ gfx/src/ps/mozilla-ps-decoder.cpp 23 Oct 2006 17:37:10 -0000
126@@ -0,0 +1,376 @@
127+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
128+/* vim:expandtab:shiftwidth=4:tabstop=4:
129+ */
130+/* ***** BEGIN LICENSE BLOCK *****
131+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
132+ *
133+ * The contents of this file are subject to the Mozilla Public License Version
134+ * 1.1 (the "License"); you may not use this file except in compliance with
135+ * the License. You may obtain a copy of the License at
136+ * http://www.mozilla.org/MPL/
137+ *
138+ * Software distributed under the License is distributed on an "AS IS" basis,
139+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
140+ * for the specific language governing rights and limitations under the
141+ * License.
142+ *
143+ * The Original Code is mozilla.org code.
144+ *
145+ * The Initial Developer of the Original Code is Christopher Blizzard
146+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
147+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
148+ *
149+ * Contributor(s):
150+ *
151+ * Alternatively, the contents of this file may be used under the terms of
152+ * either the GNU General Public License Version 2 or later (the "GPL"), or
153+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
154+ * in which case the provisions of the GPL or the LGPL are applicable instead
155+ * of those above. If you wish to allow use of your version of this file only
156+ * under the terms of either the GPL or the LGPL, and not to allow others to
157+ * use your version of this file under the terms of the MPL, indicate your
158+ * decision by deleting the provisions above and replace them with the notice
159+ * and other provisions required by the GPL or the LGPL. If you do not delete
160+ * the provisions above, a recipient may use your version of this file under
161+ * the terms of any one of the MPL, the GPL or the LGPL.
162+ *
163+ * ***** END LICENSE BLOCK ***** */
164+
165+#define PANGO_ENABLE_BACKEND
166+#define PANGO_ENABLE_ENGINE
167+
168+#include "mozilla-ps-decoder.h"
169+#include <pango/pangofc-fontmap.h>
170+#include <pango/pangofc-font.h>
171+
172+#include "nsString.h"
173+#include "nsIPersistentProperties2.h"
174+#include "nsNetUtil.h"
175+#include "nsReadableUtils.h"
176+#include "nsICharsetConverterManager.h"
177+#include "nsICharRepresentable.h"
178+#include "nsCompressedCharMap.h"
179+
180+#undef DEBUG_CUSTOM_ENCODER
181+
182+G_DEFINE_TYPE (MozillaPSDecoder, mozilla_ps_decoder, PANGO_TYPE_FC_DECODER)
183+
184+MozillaPSDecoder *mozilla_ps_decoder_new (void);
185+
186+static FcCharSet *mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder,
187+ PangoFcFont *fcfont);
188+static PangoGlyph mozilla_ps_decoder_get_glyph (PangoFcDecoder *decoder,
189+ PangoFcFont *fcfont,
190+ guint32 wc);
191+
192+static PangoFcDecoder *mozilla_find_ps_decoder (FcPattern *pattern,
193+ gpointer user_data);
194+
195+typedef struct _MozillaPSDecoderPrivate MozillaPSDecoderPrivate;
196+
197+#define MOZILLA_PS_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderPrivate))
198+
199+struct _MozillaPSDecoderPrivate {
200+ char *family;
201+ char *encoder;
202+ char *cmap;
203+ gboolean is_wide;
204+ FcCharSet *charset;
205+ nsCOMPtr<nsIUnicodeEncoder> uEncoder;
206+};
207+
208+static nsICharsetConverterManager *gCharsetManager = NULL;
209+
210+static NS_DEFINE_CID(kCharsetConverterManagerCID,
211+ NS_ICHARSETCONVERTERMANAGER_CID);
212+
213+// Hash tables that hold the custom encodings and custom cmaps used in
214+// various fonts.
215+static GHashTable *encoder_hash = NULL;
216+static GHashTable *cmap_hash = NULL;
217+static GHashTable *wide_hash = NULL;
218+
219+void
220+mozilla_ps_decoder_init (MozillaPSDecoder *decoder)
221+{
222+}
223+
224+void
225+mozilla_ps_decoder_class_init (MozillaPSDecoderClass *klass)
226+{
227+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
228+ PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
229+
230+ /* object_class->finalize = test_finalize; */
231+
232+ parent_class->get_charset = mozilla_ps_decoder_get_charset;
233+ parent_class->get_glyph = mozilla_ps_decoder_get_glyph;
234+
235+ g_type_class_add_private (object_class, sizeof (MozillaPSDecoderPrivate));
236+}
237+
238+MozillaPSDecoder *
239+mozilla_ps_decoder_new(void)
240+{
241+ return (MozillaPSDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
242+}
243+
244+#ifdef DEBUG_CUSTOM_ENCODER
245+void
246+dump_hash(char *key, char *val, void *arg)
247+{
248+ printf("%s -> %s\n", key, val);
249+}
250+#endif
251+
252+/**
253+ * mozilla_ps_decoders_init:
254+ *
255+ * #mozilla_ps_decoders_init:
256+ *
257+ * This initializes all of the application-specific custom decoders
258+ * that Mozilla uses. This should only be called once during the
259+ * lifetime of the application.
260+ *
261+ * Return value: zero on success, not zero on failure.
262+ *
263+ **/
264+
265+int
266+mozilla_ps_decoders_init(PangoFontMap *fontmap)
267+{
268+ static PRBool initialized = PR_FALSE;
269+ if (initialized)
270+ return 0;
271+
272+ if (!PANGO_IS_FC_FONT_MAP (fontmap))
273+ return -1;
274+
275+ encoder_hash = g_hash_table_new(g_str_hash, g_str_equal);
276+ cmap_hash = g_hash_table_new(g_str_hash, g_str_equal);
277+ wide_hash = g_hash_table_new(g_str_hash, g_str_equal);
278+
279+ PRBool dumb = PR_FALSE;
280+ nsCOMPtr<nsIPersistentProperties> props;
281+ nsCOMPtr<nsISimpleEnumerator> encodeEnum;
282+
283+ NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
284+ NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
285+
286+ if (!props)
287+ goto loser;
288+
289+ // Enumerate the properties in this file and figure out all of the
290+ // fonts for which we have custom encodings.
291+ props->Enumerate(getter_AddRefs(encodeEnum));
292+ if (!encodeEnum)
293+ goto loser;
294+
295+ while (encodeEnum->HasMoreElements(&dumb), dumb) {
296+ nsCOMPtr<nsIPropertyElement> prop;
297+ encodeEnum->GetNext(getter_AddRefs(prop));
298+ if (!prop)
299+ goto loser;
300+
301+ nsCAutoString name;
302+ prop->GetKey(name);
303+ nsAutoString value;
304+ prop->GetValue(value);
305+
306+ if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
307+ printf("string doesn't begin with encoding?\n");
308+ continue;
309+ }
310+
311+ name = Substring(name, 9);
312+
313+ if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
314+ name = Substring(name, 0, name.Length() - 4);
315+
316+ // Strip off a .wide if it's there.
317+ if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) {
318+ g_hash_table_insert(wide_hash, g_strdup(name.get()),
319+ g_strdup("wide"));
320+ value = Substring(value, 0, name.Length() - 5);
321+ }
322+
323+ g_hash_table_insert(encoder_hash,
324+ g_strdup(name.get()),
325+ g_strdup(NS_ConvertUTF16toUTF8(value).get()));
326+ }
327+ else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) {
328+ name = Substring(name, 0, name.Length() - 7);
329+ g_hash_table_insert(cmap_hash,
330+ g_strdup(name.get()),
331+ g_strdup(NS_ConvertUTF16toUTF8(value).get()));
332+ }
333+ else {
334+ printf("unknown suffix used for mapping\n");
335+ }
336+ }
337+
338+ pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(fontmap),
339+ mozilla_find_ps_decoder,
340+ NULL,
341+ NULL);
342+
343+ initialized = PR_TRUE;
344+
345+#ifdef DEBUG_CUSTOM_ENCODER
346+ printf("*** encoders\n");
347+ g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
348+
349+ printf("*** cmaps\n");
350+ g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
351+#endif
352+
353+ return 0;
354+
355+ loser:
356+ return -1;
357+}
358+
359+static FcCharSet *
360+mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder,
361+ PangoFcFont *fcfont)
362+{
363+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
364+
365+ if (priv->charset)
366+ return priv->charset;
367+
368+ // First time this has been accessed. Populate the charset.
369+ priv->charset = FcCharSetCreate();
370+
371+ if (!gCharsetManager) {
372+ CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
373+ }
374+
375+ nsCOMPtr<nsIUnicodeEncoder> encoder;
376+ nsCOMPtr<nsICharRepresentable> represent;
377+
378+ if (!gCharsetManager)
379+ goto end;
380+
381+ gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
382+ if (!encoder)
383+ goto end;
384+
385+ encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
386+
387+ priv->uEncoder = encoder;
388+
389+ represent = do_QueryInterface(encoder);
390+ if (!represent)
391+ goto end;
392+
393+ PRUint32 map[UCS2_MAP_LEN];
394+ memset(map, 0, sizeof(map));
395+
396+ represent->FillInfo(map);
397+
398+ for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
399+ if (IS_REPRESENTABLE(map, i))
400+ FcCharSetAddChar(priv->charset, i);
401+ }
402+
403+ end:
404+ return priv->charset;
405+}
406+
407+static PangoGlyph
408+mozilla_ps_decoder_get_glyph (PangoFcDecoder *decoder,
409+ PangoFcFont *fcfont,
410+ guint32 wc)
411+{
412+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
413+
414+ PangoGlyph retval = 0;
415+ PRUnichar inchar = wc;
416+ PRInt32 inlen = 1;
417+ char outchar[2] = {0,0};
418+ PRInt32 outlen = 2;
419+
420+ priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
421+ if (outlen != 1) {
422+ printf("Warning: mozilla_ps_decoder_get_glyph doesn't support more than one character conversions.\n");
423+ return 0;
424+ }
425+
426+ FT_Face face = pango_fc_font_lock_face(fcfont);
427+
428+#ifdef DEBUG_CUSTOM_ENCODER
429+ char *filename;
430+ FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
431+ printf("filename is %s\n", filename);
432+#endif
433+
434+ // Make sure to set the right charmap before trying to get the
435+ // glyph
436+ if (priv->cmap) {
437+ if (!strcmp(priv->cmap, "mac_roman")) {
438+ FT_Select_Charmap(face, ft_encoding_apple_roman);
439+ }
440+ else if (!strcmp(priv->cmap, "unicode")) {
441+ FT_Select_Charmap(face, ft_encoding_unicode);
442+ }
443+ else {
444+ printf("Warning: Invalid charmap entry for family %s\n",
445+ priv->family);
446+ }
447+ }
448+
449+ // Standard 8 bit to glyph translation
450+ if (!priv->is_wide) {
451+ FcChar32 blah = PRUint8(outchar[0]);
452+ retval = FT_Get_Char_Index(face, blah);
453+#ifdef DEBUG_CUSTOM_ENCODER
454+ printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n",
455+ wc, outchar[0], blah, retval, (void *)face);
456+#endif
457+ }
458+ else {
459+ printf("Warning: We don't support .wide fonts!\n");
460+ retval = 0;
461+ }
462+
463+ pango_fc_font_unlock_face(fcfont);
464+
465+ return retval;
466+}
467+
468+static PangoFcDecoder *
469+mozilla_find_ps_decoder (FcPattern *pattern, gpointer user_data)
470+{
471+ // Compare the family name of the font that's been opened to see
472+ // if we have a custom decoder.
473+ const char *orig = NULL;
474+ FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig);
475+
476+ nsCAutoString family;
477+ family.Assign(orig);
478+
479+ family.StripWhitespace();
480+ ToLowerCase(family);
481+
482+ char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
483+ if (!encoder)
484+ return NULL;
485+
486+ MozillaPSDecoder *decoder = mozilla_ps_decoder_new();
487+
488+ MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
489+
490+ priv->family = g_strdup(family.get());
491+ priv->encoder = g_strdup(encoder);
492+
493+ char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
494+ if (cmap)
495+ priv->cmap = g_strdup(cmap);
496+
497+ char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
498+ if (wide)
499+ priv->is_wide = TRUE;
500+
501+ return PANGO_FC_DECODER(decoder);
502+}
503Index: gfx/src/ps/mozilla-ps-decoder.h
504===================================================================
505RCS file: gfx/src/ps/mozilla-ps-decoder.h
506diff -N gfx/src/ps/mozilla-ps-decoder.h
507--- /dev/null 1 Jan 1970 00:00:00 -0000
508+++ gfx/src/ps/mozilla-ps-decoder.h 23 Oct 2006 17:37:10 -0000
509@@ -0,0 +1,72 @@
510+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
511+/* vim:expandtab:shiftwidth=4:tabstop=4:
512+ */
513+/* ***** BEGIN LICENSE BLOCK *****
514+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
515+ *
516+ * The contents of this file are subject to the Mozilla Public License Version
517+ * 1.1 (the "License"); you may not use this file except in compliance with
518+ * the License. You may obtain a copy of the License at
519+ * http://www.mozilla.org/MPL/
520+ *
521+ * Software distributed under the License is distributed on an "AS IS" basis,
522+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
523+ * for the specific language governing rights and limitations under the
524+ * License.
525+ *
526+ * The Original Code is mozilla.org code.
527+ *
528+ * The Initial Developer of the Original Code is Christopher Blizzard
529+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
530+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
531+ *
532+ * Contributor(s):
533+ *
534+ * Alternatively, the contents of this file may be used under the terms of
535+ * either the GNU General Public License Version 2 or later (the "GPL"), or
536+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
537+ * in which case the provisions of the GPL or the LGPL are applicable instead
538+ * of those above. If you wish to allow use of your version of this file only
539+ * under the terms of either the GPL or the LGPL, and not to allow others to
540+ * use your version of this file under the terms of the MPL, indicate your
541+ * decision by deleting the provisions above and replace them with the notice
542+ * and other provisions required by the GPL or the LGPL. If you do not delete
543+ * the provisions above, a recipient may use your version of this file under
544+ * the terms of any one of the MPL, the GPL or the LGPL.
545+ *
546+ * ***** END LICENSE BLOCK ***** */
547+
548+#ifndef _MOZILLA_PS_DECODER_H
549+#define _MOZILLA_PS_DECODER_H
550+
551+#include <pango/pangofc-decoder.h>
552+
553+G_BEGIN_DECLS
554+
555+#define MOZILLA_TYPE_DECODER (mozilla_ps_decoder_get_type())
556+#define MOZILLA_PS_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaPSDecoder))
557+#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER))
558+
559+typedef struct _MozillaPSDecoder MozillaPSDecoder;
560+typedef struct _MozillaPSDecoderClass MozillaPSDecoderClass;
561+
562+#define MOZILLA_PS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass))
563+#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER))
564+#define MOZILLA_PS_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass))
565+
566+struct _MozillaPSDecoder
567+{
568+ PangoFcDecoder parent_instance;
569+};
570+
571+struct _MozillaPSDecoderClass
572+{
573+ PangoFcDecoderClass parent_class;
574+};
575+
576+GType mozilla_ps_decoder_get_type (void);
577+int mozilla_ps_decoders_init (PangoFontMap *fontmap);
578+
579+G_END_DECLS
580+
581+#endif /*_MOZILLA_PS_DECODER_H */
582Index: gfx/src/ps/nsDeviceContextPS.cpp
583===================================================================
584RCS file: /cvsroot/mozilla/gfx/src/ps/nsDeviceContextPS.cpp,v
585retrieving revision 1.73
586diff -u -p -d -r1.73 nsDeviceContextPS.cpp
587--- gfx/src/ps/nsDeviceContextPS.cpp 21 May 2005 15:33:08 -0000 1.73
588+++ gfx/src/ps/nsDeviceContextPS.cpp 23 Oct 2006 17:37:10 -0000
589@@ -58,12 +58,15 @@
590 #include "nsIPref.h"
591 #include "nsString.h"
592 #include "nsFontMetricsPS.h"
593+#ifdef MOZ_ENABLE_PANGO
594+#include "nsFontMetricsPSPango.h"
595+#endif
596 #include "nsPostScriptObj.h"
597 #include "nspr.h"
598 #include "nsILanguageAtomService.h"
599 #include "nsPrintJobPS.h"
600 #include "nsPrintJobFactoryPS.h"
601-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
602+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
603 #include "nsType1.h"
604 #endif
605
606@@ -223,7 +226,7 @@ nsDeviceContextPS::InitDeviceContextPS(n
607
608 nsresult rv;
609 nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
610-#ifdef MOZ_ENABLE_XFT
611+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
612 if (NS_SUCCEEDED(rv)) {
613 rv = pref->GetBoolPref("font.FreeType2.printing", &mFTPEnable);
614 if (NS_FAILED(rv))
615@@ -469,7 +472,7 @@ NS_IMETHODIMP nsDeviceContextPS::EndDocu
616 NS_ASSERTION(submitFP, "No print job submission handle");
617
618 // Start writing the print job to the job handler
619-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
620+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
621 mPSObj->write_prolog(submitFP, mFTPEnable);
622 #else
623 mPSObj->write_prolog(submitFP);
624@@ -550,15 +553,52 @@ public:
625 virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** aResult);
626 };
627
628+#if defined(MOZ_ENABLE_PANGO)
629+PRBool
630+NS_IsPangoEnabled(void)
631+{
632+ static PRBool beenHere;
633+ static PRBool pangoEnabled;
634+
635+ if (!beenHere) {
636+ beenHere = PR_TRUE;
637+
638+ char *val = PR_GetEnv("MOZ_DISABLE_PANGO");
639+ pangoEnabled = !(val);
640+
641+ if (pangoEnabled) {
642+ nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID);
643+ if (prefService)
644+ prefService->SetDefaultCharPref("general.useragent.extra.pango",
645+ "pango-text");
646+ }
647+ }
648+
649+ return pangoEnabled;
650+}
651+#endif
652
653 nsresult nsFontCachePS::CreateFontMetricsInstance(nsIFontMetrics** aResult)
654 {
655 NS_PRECONDITION(aResult, "null out param");
656- nsIFontMetrics *fm = new nsFontMetricsPS();
657- if (!fm)
658- return NS_ERROR_OUT_OF_MEMORY;
659- NS_ADDREF(fm);
660- *aResult = fm;
661+#ifdef MOZ_ENABLE_PANGO
662+ if (NS_IsPangoEnabled())
663+ {
664+ nsIFontMetrics *fm = new nsFontMetricsPSPango();
665+ if (!fm)
666+ return NS_ERROR_OUT_OF_MEMORY;
667+ NS_ADDREF(fm);
668+ *aResult = fm;
669+ }
670+ else
671+#endif
672+ {
673+ nsIFontMetrics *fm = new nsFontMetricsPS();
674+ if (!fm)
675+ return NS_ERROR_OUT_OF_MEMORY;
676+ NS_ADDREF(fm);
677+ *aResult = fm;
678+ }
679 return NS_OK;
680 }
681
682Index: gfx/src/ps/nsFontMetricsPS.cpp
683===================================================================
684RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.cpp,v
685retrieving revision 1.57.16.2
686diff -u -p -d -r1.57.16.2 nsFontMetricsPS.cpp
687--- gfx/src/ps/nsFontMetricsPS.cpp 7 May 2006 02:01:25 -0000 1.57.16.2
688+++ gfx/src/ps/nsFontMetricsPS.cpp 23 Oct 2006 17:37:11 -0000
689@@ -461,6 +461,239 @@ nsFontMetricsPS :: GetStringWidth(const
690 return NS_OK;
691 }
692
693+nsresult
694+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
695+ nscoord aX, nscoord aY,
696+ const nscoord* aSpacing,
697+ nsRenderingContextPS *aContext)
698+{
699+ nsPostScriptObj* psObj = aContext->GetPostScriptObj();
700+ // When FT2 printing is enabled, we don't need to set langgroup
701+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
702+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) {
703+#endif
704+ nsCOMPtr<nsIAtom> langGroup;
705+ GetLangGroup(getter_AddRefs(langGroup));
706+ psObj->setlanggroup(langGroup);
707+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
708+ }
709+#endif
710+
711+ if (aLength == 0)
712+ return NS_OK;
713+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
714+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
715+ fontPS->SetupFont(aContext);
716+
717+ PRUint32 i, start = 0;
718+ for (i=0; i<aLength; i++) {
719+ nsFontPS* fontThisChar;
720+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this);
721+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
722+ if (fontThisChar != fontPS) {
723+ // draw text up to this point
724+ aX += DrawString(aString+start, i-start, aX, aY, fontPS,
725+ aSpacing?aSpacing+start:nsnull, aContext);
726+ start = i;
727+
728+ // setup for following text
729+ fontPS = fontThisChar;
730+ fontPS->SetupFont(aContext);
731+ }
732+ }
733+
734+ // draw the last part
735+ if (aLength-start)
736+ DrawString(aString+start, aLength-start, aX, aY, fontPS,
737+ aSpacing?aSpacing+start:nsnull, aContext);
738+
739+ return NS_OK;
740+}
741+
742+nsresult
743+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
744+ nscoord aX, nscoord aY,
745+ PRInt32 aFontID,
746+ const nscoord* aSpacing,
747+ nsRenderingContextPS *aContext)
748+{
749+ nsPostScriptObj* psObj = aContext->GetPostScriptObj();
750+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
751+ // When FT2 printing is enabled, we don't need to set langgroup
752+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) {
753+#endif
754+ nsCOMPtr<nsIAtom> langGroup = nsnull;
755+ GetLangGroup(getter_AddRefs(langGroup));
756+ psObj->setlanggroup(langGroup);
757+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
758+ }
759+#endif
760+
761+ /* build up conversion table */
762+ psObj->preshow(aString, aLength);
763+
764+ if (aLength == 0)
765+ return NS_OK;
766+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
767+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
768+ fontPS->SetupFont(aContext);
769+
770+ PRUint32 i, start = 0;
771+ for (i=0; i<aLength; i++) {
772+ nsFontPS* fontThisChar;
773+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this);
774+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
775+ if (fontThisChar != fontPS) {
776+ // draw text up to this point
777+ aX += DrawString(aString+start, i-start, aX, aY, fontPS,
778+ aSpacing?aSpacing+start:nsnull, aContext);
779+ start = i;
780+
781+ // setup for following text
782+ fontPS = fontThisChar;
783+ fontPS->SetupFont(aContext);
784+ }
785+ }
786+
787+ // draw the last part
788+ if (aLength-start)
789+ DrawString(aString+start, aLength-start, aX, aY, fontPS,
790+ aSpacing?aSpacing+start:nsnull, aContext);
791+
792+ return NS_OK;
793+}
794+
795+PRInt32
796+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
797+ nscoord aX, nscoord aY, nsFontPS* aFontPS,
798+ const nscoord* aSpacing,
799+ nsRenderingContextPS *aContext)
800+{
801+ nscoord width = 0;
802+ PRInt32 x = aX;
803+ PRInt32 y = aY;
804+
805+ PRInt32 dxMem[500];
806+ PRInt32* dx0 = 0;
807+ if (aSpacing) {
808+ dx0 = dxMem;
809+ if (aLength > 500) {
810+ dx0 = new PRInt32[aLength];
811+ NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
812+ }
813+ aContext->GetTranMatrix()->ScaleXCoords(aSpacing, aLength, dx0);
814+ }
815+
816+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
817+ width = aFontPS->DrawString(aContext, x, y, aString, aLength);
818+
819+ if ((aSpacing) && (dx0 != dxMem)) {
820+ delete [] dx0;
821+ }
822+
823+ return width;
824+}
825+
826+
827+PRInt32
828+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
829+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
830+ const nscoord* aSpacing,
831+ nsRenderingContextPS *aContext)
832+{
833+ nscoord width = 0;
834+ PRInt32 x = aX;
835+ PRInt32 y = aY;
836+
837+ if (aSpacing) {
838+ // Slow, but accurate rendering
839+ const PRUnichar* end = aString + aLength;
840+ while (aString < end){
841+ x = aX;
842+ y = aY;
843+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
844+ aFontPS->DrawString(aContext, x, y, aString, 1);
845+ aX += *aSpacing++;
846+ aString++;
847+ }
848+ width = aX;
849+ } else {
850+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
851+ width = aFontPS->DrawString(aContext, x, y, aString, aLength);
852+ }
853+
854+ return width;
855+}
856+
857+NS_IMETHODIMP
858+nsFontMetricsPS::GetTextDimensions(const char* aString,
859+ PRInt32 aLength,
860+ PRInt32 aAvailWidth,
861+ PRInt32* aBreaks,
862+ PRInt32 aNumBreaks,
863+ nsTextDimensions& aDimensions,
864+ PRInt32& aNumCharsFit,
865+ nsTextDimensions& aLastWordDimensions,
866+ PRInt32* aFontID)
867+{
868+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
869+ return NS_ERROR_NOT_IMPLEMENTED;
870+}
871+
872+NS_IMETHODIMP
873+nsFontMetricsPS::GetTextDimensions(const PRUnichar* aString,
874+ PRInt32 aLength,
875+ PRInt32 aAvailWidth,
876+ PRInt32* aBreaks,
877+ PRInt32 aNumBreaks,
878+ nsTextDimensions& aDimensions,
879+ PRInt32& aNumCharsFit,
880+ nsTextDimensions& aLastWordDimensions,
881+ PRInt32* aFontID)
882+{
883+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
884+ return NS_ERROR_NOT_IMPLEMENTED;
885+}
886+
887+NS_IMETHODIMP
888+nsFontMetricsPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
889+ nsTextDimensions& aDimensions)
890+{
891+ GetStringWidth(aString, aDimensions.width, aLength);
892+ GetMaxAscent(aDimensions.ascent);
893+ GetMaxDescent(aDimensions.descent);
894+ return NS_OK;
895+}
896+
897+NS_IMETHODIMP
898+nsFontMetricsPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
899+ nsTextDimensions& aDimensions, PRInt32* aFontID)
900+{
901+ GetStringWidth(aString, aDimensions.width, aLength);
902+ //XXX temporary - bug 96609
903+ GetMaxAscent(aDimensions.ascent);
904+ GetMaxDescent(aDimensions.descent);
905+ return NS_OK;
906+}
907+
908+nsresult
909+nsFontMetricsPS::GetBoundingMetrics(const char* aString,
910+ PRUint32 aLength,
911+ nsBoundingMetrics& aBoundingMetrics)
912+{
913+ return NS_ERROR_NOT_IMPLEMENTED;
914+}
915+
916+nsresult
917+nsFontMetricsPS::GetBoundingMetrics(const PRUnichar* aString,
918+ PRUint32 aLength,
919+ nsBoundingMetrics &aBoundingMetrics,
920+ PRInt32 *aFontID)
921+{
922+ return NS_ERROR_NOT_IMPLEMENTED;
923+}
924+
925+
926 nsFontPS*
927 nsFontPS::FindFont(char aChar, const nsFont& aFont,
928 nsFontMetricsPS* aFontMetrics)
929@@ -1128,23 +1361,38 @@ nsFontPSXft::DrawString(nsRenderingConte
930 PRUint32 start = 0;
931 PRUint32 i;
932
933+ FT_Face face = getFTFace();
934+ if (!face) {
935+ NS_WARNING("Failed to get FT Face in nsFontPSXft::DrawString\n");
936+ return 0;
937+ }
938+
939+ nsValueArray glyphs(PR_UINT16_MAX);
940+
941 // XXX : ignore surrogate pairs for now
942- nsString *subSet = mPSFontGenerator->GetSubset();
943 for (i = 0; i < aLength; ++i) {
944- currSubFont = mPSFontGenerator->AddToSubset(aString[i]);
945+ PRUint32 glyph = FT_Get_Char_Index(face, aString[i]);
946+ currSubFont = mPSFontGenerator->AddToGlyphSubset(glyph);
947+
948+ // Check if we need to render the current string
949 if (prevSubFont != currSubFont) {
950- if (prevSubFont != -1)
951- psObj->show(&aString[start], i - start, *subSet, prevSubFont);
952+ if (prevSubFont != -1) {
953+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont);
954+ }
955 NS_ASSERTION(!mFontNameBase.IsEmpty(),
956 "font base name shouldn't be empty");
957 psObj->setfont(mFontNameBase, mHeight, currSubFont);
958 prevSubFont = currSubFont;
959 start = i;
960+ glyphs.Clear();
961 }
962+
963+ glyphs.AppendValue(glyph);
964 }
965
966- if (prevSubFont != -1)
967- psObj->show(&aString[start], i - start, *subSet, prevSubFont);
968+ if (prevSubFont != -1) {
969+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont);
970+ }
971
972 return GetWidth(aString, aLength);
973 }
974@@ -2278,10 +2526,13 @@ nsFontPSFreeType::GetBoundingMetrics(con
975 // Implementation of nsPSFontGenerator
976 nsPSFontGenerator::nsPSFontGenerator()
977 {
978+ mGlyphSubset = new nsValueArray(PR_UINT16_MAX, 40);
979 }
980
981 nsPSFontGenerator::~nsPSFontGenerator()
982 {
983+ if (mGlyphSubset)
984+ delete mGlyphSubset;
985 }
986
987 void nsPSFontGenerator::GeneratePSFont(FILE* aFile)
988@@ -2289,24 +2540,29 @@ void nsPSFontGenerator::GeneratePSFont(F
989 NS_ERROR("should never call nsPSFontGenerator::GeneratePSFont");
990 }
991
992-// Add a Unicode character to mSubset which will be divided into
993-// multiple chunks (subfonts) of 255 (kSubFontSize) characters each.
994-// Each chunk will be converted to a Type 1 font. Return the index of
995-// a subfont (chunk) this character belongs to.
996+// Add a glyph offset to mSubset which will be divided into multiple
997+// chunks (subfonts) of 255 (kSubFontSize) glyphs each. Each chunk
998+// will then be converted into a Type 1 font. Return the index of a
999+// subfont (chunk) this glyph belongs to.
1000 PRInt32
1001-nsPSFontGenerator::AddToSubset(PRUnichar aChar)
1002+nsPSFontGenerator::AddToGlyphSubset(PRUint32 aGlyph)
1003 {
1004- PRInt32 index = mSubset.FindChar(aChar);
1005- if (index == kNotFound) {
1006- mSubset.Append(aChar);
1007- index = mSubset.Length() - 1;
1008+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph);
1009+ if (index == NSVALUEARRAY_INVALID) {
1010+ mGlyphSubset->AppendValue(aGlyph);
1011+ index = mGlyphSubset->Count() - 1;
1012 }
1013+
1014 return index / kSubFontSize;
1015 }
1016
1017-nsString *nsPSFontGenerator::GetSubset()
1018+PRInt32
1019+nsPSFontGenerator::InSubsetIndexOf(PRUint32 aGlyph)
1020 {
1021- return &mSubset;
1022+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph);
1023+ if (index == NSVALUEARRAY_INVALID)
1024+ return 0;
1025+ return (index % kSubFontSize) + 1;
1026 }
1027
1028 #ifdef MOZ_ENABLE_XFT
1029@@ -2353,8 +2609,8 @@ void nsXftType1Generator::GeneratePSFont
1030 }
1031
1032 int wmode = 0;
1033- if (!mSubset.IsEmpty())
1034- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
1035+ if (mGlyphSubset->Count())
1036+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
1037 }
1038
1039 #else
1040@@ -2402,8 +2658,8 @@ void nsFT2Type1Generator::GeneratePSFont
1041 return;
1042
1043 int wmode = 0;
1044- if (!mSubset.IsEmpty())
1045- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
1046+ if (mGlyphSubset->Count())
1047+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
1048 }
1049
1050 #endif //MOZ_ENABLE_FREETYPE2
1051Index: gfx/src/ps/nsFontMetricsPS.h
1052===================================================================
1053RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.h,v
1054retrieving revision 1.31
1055diff -u -p -d -r1.31 nsFontMetricsPS.h
1056--- gfx/src/ps/nsFontMetricsPS.h 28 Jun 2005 18:29:10 -0000 1.31
1057+++ gfx/src/ps/nsFontMetricsPS.h 23 Oct 2006 17:37:11 -0000
1058@@ -66,6 +66,7 @@
1059 #endif
1060 #include "nsVoidArray.h"
1061 #include "nsHashtable.h"
1062+#include "nsValueArray.h"
1063
1064 class nsPSFontGenerator;
1065 class nsDeviceContextPS;
1066@@ -108,6 +109,65 @@ public:
1067 NS_IMETHOD GetFontHandle(nsFontHandle &aHandle);
1068 NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
1069 NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
1070+
1071+ NS_IMETHOD GetTextDimensions(const char* aString,
1072+ PRUint32 aLength,
1073+ nsTextDimensions& aDimensions);
1074+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
1075+ PRUint32 aLength,
1076+ nsTextDimensions& aDimensions,
1077+ PRInt32* aFontID);
1078+ NS_IMETHOD GetTextDimensions(const char* aString,
1079+ PRInt32 aLength,
1080+ PRInt32 aAvailWidth,
1081+ PRInt32* aBreaks,
1082+ PRInt32 aNumBreaks,
1083+ nsTextDimensions& aDimensions,
1084+ PRInt32& aNumCharsFit,
1085+ nsTextDimensions& aLastWordDimensions,
1086+ PRInt32* aFontID);
1087+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
1088+ PRInt32 aLength,
1089+ PRInt32 aAvailWidth,
1090+ PRInt32* aBreaks,
1091+ PRInt32 aNumBreaks,
1092+ nsTextDimensions& aDimensions,
1093+ PRInt32& aNumCharsFit,
1094+ nsTextDimensions& aLastWordDimensions,
1095+ PRInt32* aFontID);
1096+#ifdef MOZ_MATHML
1097+ NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
1098+ nsBoundingMetrics &aBoundingMetrics);
1099+ NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString,
1100+ PRUint32 aLength,
1101+ nsBoundingMetrics &aBoundingMetrics,
1102+ PRInt32 *aFontID);
1103+#endif /* MOZ_MATHML */
1104+
1105+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
1106+ nscoord aX, nscoord aY,
1107+ const nscoord* aSpacing,
1108+ nsRenderingContextPS *aContext);
1109+ NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
1110+ nscoord aX, nscoord aY,
1111+ PRInt32 aFontID,
1112+ const nscoord* aSpacing,
1113+ nsRenderingContextPS *aContext);
1114+
1115+protected:
1116+ PRInt32 DrawString(const char *aString, PRUint32 aLength,
1117+ nscoord aX, nscoord aY, nsFontPS* aFontPS,
1118+ const nscoord* aSpacing,
1119+ nsRenderingContextPS *aContext);
1120+ PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength,
1121+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
1122+ const nscoord* aSpacing,
1123+ nsRenderingContextPS *aContext);
1124+
1125+public:
1126+
1127+ virtual PRUint32 GetHints (void) { return 0; }
1128+
1129
1130 inline void SetXHeight(nscoord aXHeight) { mXHeight = aXHeight; };
1131 inline void SetSuperscriptOffset(nscoord aSuperscriptOffset) { mSuperscriptOffset = aSuperscriptOffset; };
1132@@ -455,16 +515,14 @@ public:
1133 nsPSFontGenerator();
1134 virtual ~nsPSFontGenerator();
1135 virtual void GeneratePSFont(FILE* aFile);
1136- PRInt32 AddToSubset(PRUnichar aChar);
1137- nsString *GetSubset();
1138+ PRInt32 AddToGlyphSubset(PRUint32 aGlyph);
1139+ PRInt32 InSubsetIndexOf(PRUint32 aGlyph);
1140
1141 // 256 (PS type 1 encoding vector size) - 1 (1 is for mandatory /.notdef)
1142 const static PRUint16 kSubFontSize;
1143
1144 protected:
1145- // XXX To support non-BMP characters, we may have to use
1146- // nsValueArray with PRUint32
1147- nsString mSubset;
1148+ nsValueArray *mGlyphSubset;
1149 };
1150
1151
1152Index: gfx/src/ps/nsFontMetricsPSPango.cpp
1153===================================================================
1154RCS file: gfx/src/ps/nsFontMetricsPSPango.cpp
1155diff -N gfx/src/ps/nsFontMetricsPSPango.cpp
1156--- /dev/null 1 Jan 1970 00:00:00 -0000
1157+++ gfx/src/ps/nsFontMetricsPSPango.cpp 23 Oct 2006 17:37:13 -0000
1158@@ -0,0 +1,2107 @@
1159+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
1160+/* vim:expandtab:shiftwidth=4:tabstop=4:
1161+ */
1162+/* ***** BEGIN LICENSE BLOCK *****
1163+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
1164+ *
1165+ * The contents of this file are subject to the Mozilla Public License Version
1166+ * 1.1 (the "License"); you may not use this file except in compliance with
1167+ * the License. You may obtain a copy of the License at
1168+ * http://www.mozilla.org/MPL/
1169+ *
1170+ * Software distributed under the License is distributed on an "AS IS" basis,
1171+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1172+ * for the specific language governing rights and limitations under the
1173+ * License.
1174+ *
1175+ * The Original Code is mozilla.org code.
1176+ *
1177+ * The Initial Developer of the Original Code is Christopher Blizzard
1178+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
1179+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
1180+ *
1181+ * Contributor(s):
1182+ * Christopher Blizzard <blizzard@mozilla.org>
1183+ * Behdad Esfahbod <behdad@behdad.org>
1184+ *
1185+ * Alternatively, the contents of this file may be used under the terms of
1186+ * either the GNU General Public License Version 2 or later (the "GPL"), or
1187+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1188+ * in which case the provisions of the GPL or the LGPL are applicable instead
1189+ * of those above. If you wish to allow use of your version of this file only
1190+ * under the terms of either the GPL or the LGPL, and not to allow others to
1191+ * use your version of this file under the terms of the MPL, indicate your
1192+ * decision by deleting the provisions above and replace them with the notice
1193+ * and other provisions required by the GPL or the LGPL. If you do not delete
1194+ * the provisions above, a recipient may use your version of this file under
1195+ * the terms of any one of the MPL, the GPL or the LGPL.
1196+ *
1197+ * ***** END LICENSE BLOCK ***** */
1198+
1199+#include <strings.h>
1200+#include "nsFont.h"
1201+#include "nsIDeviceContext.h"
1202+#include "nsICharsetConverterManager.h"
1203+#include "nsIPref.h"
1204+#include "nsServiceManagerUtils.h"
1205+
1206+#define PANGO_ENABLE_BACKEND
1207+#define PANGO_ENABLE_ENGINE
1208+
1209+#include "nsFontMetricsPSPango.h"
1210+#include "nsRenderingContextPS.h"
1211+#include "nsDeviceContextPS.h"
1212+#include "nsFontConfigUtils.h"
1213+
1214+#include "nsPrintfCString.h"
1215+#include "nsUnicharUtils.h"
1216+#include "nsQuickSort.h"
1217+#include "nsFontConfigUtils.h"
1218+
1219+#include <fontconfig/fontconfig.h>
1220+#include <pango/pangoft2.h>
1221+#include <freetype/tttables.h>
1222+#include "nsType1.h"
1223+
1224+#include "mozilla-ps-decoder.h"
1225+
1226+#define FORCE_PR_LOG
1227+#include "prlog.h"
1228+
1229+// Globals
1230+
1231+static PRLogModuleInfo *gPangoFontLog;
1232+static int gNumInstances;
1233+
1234+
1235+static void
1236+default_substitute (FcPattern *pattern,
1237+ gpointer data)
1238+{
1239+ FcPatternDel (pattern, FC_HINTING);
1240+ FcPatternAddBool (pattern, FC_HINTING, 0);
1241+}
1242+
1243+static PangoFontMap *
1244+get_fontmap (void)
1245+{
1246+ static PangoFontMap *fontmap = NULL;
1247+
1248+ if (!fontmap) {
1249+ fontmap = pango_ft2_font_map_new ();
1250+ pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.);
1251+ pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL);
1252+ }
1253+
1254+ return fontmap;
1255+}
1256+
1257+static PangoContext *
1258+get_context (void)
1259+{
1260+ return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
1261+}
1262+
1263+// Defines
1264+
1265+// This is the scaling factor that we keep fonts limited to against
1266+// the display size. If a pixel size is requested that is more than
1267+// this factor larger than the height of the display, it's clamped to
1268+// that value instead of the requested size.
1269+#define FONT_MAX_FONT_SCALE 2
1270+
1271+static NS_DEFINE_CID(kCharsetConverterManagerCID,
1272+ NS_ICHARSETCONVERTERMANAGER_CID);
1273+
1274+#ifdef DEBUG
1275+#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \
1276+ printf("0x%x ", ustr[llen]); \
1277+ printf("\n");
1278+#endif
1279+
1280+// rounding and truncation functions for a Freetype floating point number
1281+// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
1282+// part and low 6 bits for the fractional part.
1283+#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
1284+#define MOZ_FT_TRUNC(x) ((x) >> 6)
1285+#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
1286+ MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
1287+
1288+// Static function decls
1289+
1290+static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup);
1291+
1292+static void FreeGlobals (void);
1293+
1294+static PangoStyle CalculateStyle (PRUint8 aStyle);
1295+static PangoWeight CalculateWeight (PRUint16 aWeight);
1296+
1297+static nsresult EnumFontsPango (nsIAtom* aLangGroup, const char* aGeneric,
1298+ PRUint32* aCount, PRUnichar*** aResult);
1299+static int CompareFontNames (const void* aArg1, const void* aArg2,
1300+ void* aClosure);
1301+
1302+nsFontMetricsPSPango::nsFontMetricsPSPango()
1303+{
1304+ if (!gPangoFontLog)
1305+ gPangoFontLog = PR_NewLogModule("PangoFont");
1306+
1307+ gNumInstances++;
1308+
1309+ mPangoFontDesc = nsnull;
1310+ mPangoContext = nsnull;
1311+ mLTRPangoContext = nsnull;
1312+ mRTLPangoContext = nsnull;
1313+ mPangoAttrList = nsnull;
1314+ mIsRTL = PR_FALSE;
1315+ mPangoSpaceWidth = 0;
1316+
1317+ static PRBool initialized = PR_FALSE;
1318+ if (initialized)
1319+ return;
1320+
1321+ // Initialized the custom decoders
1322+ if (!mozilla_ps_decoders_init(get_fontmap ()))
1323+ initialized = PR_TRUE;
1324+}
1325+
1326+nsFontMetricsPSPango::~nsFontMetricsPSPango()
1327+{
1328+ if (mDeviceContext)
1329+ mDeviceContext->FontMetricsDeleted(this);
1330+
1331+ if (mPangoFontDesc)
1332+ pango_font_description_free(mPangoFontDesc);
1333+
1334+ if (mLTRPangoContext)
1335+ g_object_unref(mLTRPangoContext);
1336+
1337+ if (mRTLPangoContext)
1338+ g_object_unref(mRTLPangoContext);
1339+
1340+ if (mPangoAttrList)
1341+ pango_attr_list_unref(mPangoAttrList);
1342+
1343+ // XXX clean up all the pango objects
1344+
1345+ if (--gNumInstances == 0)
1346+ FreeGlobals();
1347+}
1348+
1349+
1350+NS_IMPL_ISUPPORTS1(nsFontMetricsPSPango, nsIFontMetrics)
1351+
1352+// nsIFontMetrics impl
1353+
1354+NS_IMETHODIMP
1355+nsFontMetricsPSPango::Init(const nsFont& aFont, nsIAtom* aLangGroup,
1356+ nsIDeviceContext *aContext)
1357+{
1358+ mFont = aFont;
1359+ mLangGroup = aLangGroup;
1360+
1361+ // Hang on to the device context
1362+ mDeviceContext = aContext;
1363+
1364+ mPointSize = NSTwipsToFloatPoints(mFont.size);
1365+
1366+ // enumerate over the font names passed in
1367+ mFont.EnumerateFamilies(nsFontMetricsPSPango::EnumFontCallback, this);
1368+
1369+ nsCOMPtr<nsIPref> prefService;
1370+ prefService = do_GetService(NS_PREF_CONTRACTID);
1371+ if (!prefService)
1372+ return NS_ERROR_FAILURE;
1373+
1374+ nsXPIDLCString value;
1375+ const char* langGroup;
1376+ mLangGroup->GetUTF8String(&langGroup);
1377+
1378+ // Set up the default font name if it's not set
1379+ if (!mGenericFont) {
1380+ nsCAutoString name("font.default.");
1381+ name.Append(langGroup);
1382+ prefService->CopyCharPref(name.get(), getter_Copies(value));
1383+
1384+ if (value.get())
1385+ mDefaultFont = value.get();
1386+ else
1387+ mDefaultFont = "serif";
1388+
1389+ mGenericFont = &mDefaultFont;
1390+ }
1391+
1392+ // set up the minimum sizes for fonts
1393+ if (mLangGroup) {
1394+ nsCAutoString name("font.min-size.");
1395+
1396+ if (mGenericFont->Equals("monospace"))
1397+ name.Append("fixed");
1398+ else
1399+ name.Append("variable");
1400+
1401+ name.Append(char('.'));
1402+ name.Append(langGroup);
1403+
1404+ PRInt32 minimumInt = 0;
1405+ float minimum;
1406+ nsresult res;
1407+ res = prefService->GetIntPref(name.get(), &minimumInt);
1408+ if (NS_FAILED(res))
1409+ prefService->GetDefaultIntPref(name.get(), &minimumInt);
1410+
1411+ if (minimumInt < 0)
1412+ minimumInt = 0;
1413+
1414+ minimum = minimumInt;
1415+
1416+ // The minimum size is specified in pixels, not in points.
1417+ // Convert the size from pixels to points.
1418+ minimum = NSTwipsToFloatPoints(NSFloatPixelsToTwips(minimum, mDeviceContext->DevUnitsToAppUnits()));
1419+ if (mPointSize < minimum)
1420+ mPointSize = minimum;
1421+ }
1422+
1423+ // Make sure that the pixel size is at least greater than zero
1424+ if (mPointSize < 1) {
1425+#ifdef DEBUG
1426+ printf("*** Warning: nsFontMetricsPSPango created with point size %f\n",
1427+ mPointSize);
1428+#endif
1429+ mPointSize = 1;
1430+ }
1431+
1432+ nsresult rv = RealizeFont();
1433+ if (NS_FAILED(rv))
1434+ return rv;
1435+
1436+ // Cache font metrics for the 'x' character
1437+ return CacheFontMetrics();
1438+}
1439+
1440+nsresult
1441+nsFontMetricsPSPango::CacheFontMetrics(void)
1442+{
1443+ // Get our scale factor
1444+ float f;
1445+ float val;
1446+ f = mDeviceContext->DevUnitsToAppUnits();
1447+
1448+ mPangoAttrList = pango_attr_list_new();
1449+
1450+ GList *items = pango_itemize(mPangoContext,
1451+ "a", 0, 1, mPangoAttrList, NULL);
1452+
1453+ if (!items)
1454+ return NS_ERROR_FAILURE;
1455+
1456+ guint nitems = g_list_length(items);
1457+ if (nitems != 1)
1458+ return NS_ERROR_FAILURE;
1459+
1460+ PangoItem *item = (PangoItem *)items->data;
1461+ PangoFcFont *fcfont = PANGO_FC_FONT(item->analysis.font);
1462+ if (!fcfont)
1463+ return NS_ERROR_FAILURE;
1464+
1465+ // Get our font face
1466+ FT_Face face;
1467+ face = pango_fc_font_lock_face(fcfont);
1468+ if (!face)
1469+ return NS_ERROR_NOT_AVAILABLE;
1470+
1471+ TT_OS2 *os2;
1472+ os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1473+
1474+ // mEmHeight (size in pixels of EM height)
1475+ int size;
1476+ if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) !=
1477+ FcResultMatch) {
1478+ size = 12;
1479+ }
1480+ mEmHeight = PR_MAX(1, nscoord(size * f));
1481+
1482+ // mMaxAscent
1483+ val = MOZ_FT_TRUNC(face->size->metrics.ascender);
1484+ mMaxAscent = NSToIntRound(val * f);
1485+
1486+ // mMaxDescent
1487+ val = -MOZ_FT_TRUNC(face->size->metrics.descender);
1488+ mMaxDescent = NSToIntRound(val * f);
1489+
1490+ nscoord lineHeight = mMaxAscent + mMaxDescent;
1491+
1492+ // mLeading (needs ascent and descent and EM height)
1493+ if (lineHeight > mEmHeight)
1494+ mLeading = lineHeight - mEmHeight;
1495+ else
1496+ mLeading = 0;
1497+
1498+ // mMaxHeight (needs ascent and descent)
1499+ mMaxHeight = lineHeight;
1500+
1501+ // mEmAscent (needs maxascent, EM height, ascent and descent)
1502+ mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight);
1503+
1504+ // mEmDescent (needs EM height and EM ascent
1505+ mEmDescent = mEmHeight - mEmAscent;
1506+
1507+ // mMaxAdvance
1508+ val = MOZ_FT_TRUNC(face->size->metrics.max_advance);
1509+ mMaxAdvance = NSToIntRound(val * f);
1510+
1511+ // mPangoSpaceWidth
1512+ PangoLayout *layout = pango_layout_new(mPangoContext);
1513+ pango_layout_set_text(layout, " ", 1);
1514+ int pswidth, psheight;
1515+ pango_layout_get_size(layout, &pswidth, &psheight);
1516+ mPangoSpaceWidth = pswidth;
1517+ g_object_unref(layout);
1518+
1519+ // mSpaceWidth (width of a space)
1520+ nscoord tmpWidth;
1521+ GetWidth(" ", 1, tmpWidth);
1522+ mSpaceWidth = tmpWidth;
1523+
1524+ // mAveCharWidth (width of an 'average' char)
1525+ // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
1526+ //rawWidth = extents.width;
1527+ //mAveCharWidth = NSToCoordRound(rawWidth * f);
1528+ GetWidth("x", 1, tmpWidth);
1529+ mAveCharWidth = tmpWidth;
1530+
1531+ // mXHeight (height of an 'x' character)
1532+ if (pango_fc_font_has_char(fcfont, 'x')) {
1533+ PangoRectangle rect;
1534+ PangoGlyph glyph = pango_fc_font_get_glyph (fcfont, 'x');
1535+ pango_font_get_glyph_extents (PANGO_FONT (fcfont), glyph, &rect, NULL);
1536+ mXHeight = NSToIntRound(rect.height * f / PANGO_SCALE);
1537+ }
1538+ else {
1539+ // 56% of ascent, best guess for non-true type or asian fonts
1540+ mXHeight = nscoord(((float)mMaxAscent) * 0.56 * f);
1541+ }
1542+
1543+ // mUnderlineOffset (offset for underlines)
1544+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position,
1545+ face->size->metrics.y_scale);
1546+ if (val) {
1547+ mUnderlineOffset = NSToIntRound(val * f);
1548+ }
1549+ else {
1550+ mUnderlineOffset =
1551+ -NSToIntRound(PR_MAX(1, floor(0.1 *
1552+ MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
1553+ }
1554+
1555+ // mUnderlineSize (thickness of an underline)
1556+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness,
1557+ face->size->metrics.y_scale);
1558+ if (val) {
1559+ mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1560+ }
1561+ else {
1562+ mUnderlineSize =
1563+ NSToIntRound(PR_MAX(1,
1564+ floor(0.05 * MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
1565+ }
1566+
1567+ // mSuperscriptOffset
1568+ if (os2 && os2->ySuperscriptYOffset) {
1569+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySuperscriptYOffset,
1570+ face->size->metrics.y_scale);
1571+ mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1572+ }
1573+ else {
1574+ mSuperscriptOffset = mXHeight;
1575+ }
1576+
1577+ // mSubscriptOffset
1578+ if (os2 && os2->ySubscriptYOffset) {
1579+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySubscriptYOffset,
1580+ face->size->metrics.y_scale);
1581+ // some fonts have the incorrect sign.
1582+ val = (val < 0) ? -val : val;
1583+ mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1584+ }
1585+ else {
1586+ mSubscriptOffset = mXHeight;
1587+ }
1588+
1589+ // mStrikeoutOffset
1590+ mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
1591+
1592+ // mStrikeoutSize
1593+ mStrikeoutSize = mUnderlineSize;
1594+
1595+ pango_fc_font_unlock_face(fcfont);
1596+
1597+ /*
1598+ printf("%i\n", mXHeight);
1599+ printf("%i\n", mSuperscriptOffset);
1600+ printf("%i\n", mSubscriptOffset);
1601+ printf("%i\n", mStrikeoutOffset);
1602+ printf("%i\n", mStrikeoutSize);
1603+ printf("%i\n", mUnderlineOffset);
1604+ printf("%i\n", mUnderlineSize);
1605+ printf("%i\n", mMaxHeight);
1606+ printf("%i\n", mLeading);
1607+ printf("%i\n", mEmHeight);
1608+ printf("%i\n", mEmAscent);
1609+ printf("%i\n", mEmDescent);
1610+ printf("%i\n", mMaxAscent);
1611+ printf("%i\n", mMaxDescent);
1612+ printf("%i\n", mMaxAdvance);
1613+ printf("%i\n", mSpaceWidth);
1614+ printf("%i\n", mAveCharWidth);
1615+ */
1616+
1617+ return NS_OK;
1618+}
1619+
1620+NS_IMETHODIMP
1621+nsFontMetricsPSPango::Destroy()
1622+{
1623+ mDeviceContext = nsnull;
1624+ return NS_OK;
1625+}
1626+
1627+NS_IMETHODIMP
1628+nsFontMetricsPSPango::GetLangGroup(nsIAtom** aLangGroup)
1629+{
1630+ *aLangGroup = mLangGroup;
1631+ NS_IF_ADDREF(*aLangGroup);
1632+
1633+ return NS_OK;
1634+}
1635+
1636+NS_IMETHODIMP
1637+nsFontMetricsPSPango::GetFontHandle(nsFontHandle &aHandle)
1638+{
1639+ return NS_ERROR_NOT_IMPLEMENTED;
1640+}
1641+
1642+// nsIFontMetricsPango impl
1643+NS_IMETHODIMP
1644+nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
1645+{
1646+ return GetWidth (String, (PRUint32) aLength, aWidth);
1647+}
1648+
1649+NS_IMETHODIMP
1650+nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
1651+{
1652+ return GetWidth (aString, (PRUint32)aLength, aWidth);
1653+}
1654+
1655+nsresult
1656+nsFontMetricsPSPango::GetWidth(const char* aString, PRUint32 aLength,
1657+ nscoord& aWidth)
1658+{
1659+ PangoLayout *layout = pango_layout_new(mPangoContext);
1660+
1661+ pango_layout_set_text(layout, aString, aLength);
1662+
1663+ if (mPangoSpaceWidth)
1664+ FixupSpaceWidths(layout, aString);
1665+
1666+ int width, height;
1667+
1668+ pango_layout_get_size(layout, &width, &height);
1669+
1670+ g_object_unref(layout);
1671+
1672+ float f;
1673+ f = mDeviceContext->DevUnitsToAppUnits();
1674+ aWidth = NSToCoordRound(width * f / PANGO_SCALE);
1675+
1676+ // printf("GetWidth (char *) %d\n", aWidth);
1677+
1678+ return NS_OK;
1679+}
1680+
1681+nsresult
1682+nsFontMetricsPSPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
1683+ nscoord& aWidth)
1684+{
1685+ nsresult rv = NS_OK;
1686+ PangoLayout *layout = pango_layout_new(mPangoContext);
1687+
1688+ gchar *text = g_utf16_to_utf8(aString, aLength,
1689+ NULL, NULL, NULL);
1690+
1691+ if (!text) {
1692+ aWidth = 0;
1693+#ifdef DEBUG
1694+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
1695+ DUMP_PRUNICHAR(aString, aLength)
1696+#endif
1697+ rv = NS_ERROR_FAILURE;
1698+ goto loser;
1699+ }
1700+
1701+ gint width, height;
1702+
1703+ pango_layout_set_text(layout, text, strlen(text));
1704+ FixupSpaceWidths(layout, text);
1705+ pango_layout_get_size(layout, &width, &height);
1706+
1707+ float f;
1708+ f = mDeviceContext->DevUnitsToAppUnits();
1709+ aWidth = NSToCoordRound(width * f / PANGO_SCALE);
1710+
1711+ // printf("GetWidth %d\n", aWidth);
1712+
1713+ loser:
1714+ g_free(text);
1715+ g_object_unref(layout);
1716+
1717+ return rv;
1718+}
1719+
1720+
1721+nsresult
1722+nsFontMetricsPSPango :: GetTextDimensions(const char* aString, PRUint32 aLength,
1723+ nsTextDimensions& aDimensions)
1724+{
1725+ nsresult rv = NS_OK;
1726+
1727+ PangoLayout *layout = pango_layout_new(mPangoContext);
1728+
1729+ pango_layout_set_text(layout, aString, aLength);
1730+ FixupSpaceWidths(layout,aString);
1731+
1732+ // Get the logical extents
1733+ PangoLayoutLine *line;
1734+ if (pango_layout_get_line_count(layout) != 1) {
1735+ printf("Warning: more than one line!\n");
1736+ }
1737+ line = pango_layout_get_line(layout, 0);
1738+
1739+ PangoRectangle rect;
1740+ pango_layout_line_get_extents(line, NULL, &rect);
1741+
1742+ float P2T;
1743+ P2T = mDeviceContext->DevUnitsToAppUnits();
1744+
1745+ aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
1746+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
1747+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
1748+
1749+ // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
1750+ //aDimensions.ascent, aDimensions.descent);
1751+
1752+ loser:
1753+ g_object_unref(layout);
1754+
1755+ return rv;
1756+}
1757+
1758+nsresult
1759+nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString,
1760+ PRUint32 aLength,
1761+ nsTextDimensions& aDimensions,
1762+ PRInt32* aFontID)
1763+{
1764+ nsresult rv = NS_OK;
1765+
1766+ PangoLayout *layout = pango_layout_new(mPangoContext);
1767+
1768+ gchar *text = g_utf16_to_utf8(aString, aLength,
1769+ NULL, NULL, NULL);
1770+
1771+ if (!text) {
1772+#ifdef DEBUG
1773+ NS_WARNING("nsFontMetricsPSPango::GetTextDimensions invalid unicode to follow");
1774+ DUMP_PRUNICHAR(aString, aLength)
1775+#endif
1776+ aDimensions.width = 0;
1777+ aDimensions.ascent = 0;
1778+ aDimensions.descent = 0;
1779+
1780+ rv = NS_ERROR_FAILURE;
1781+ goto loser;
1782+ }
1783+
1784+
1785+ pango_layout_set_text(layout, text, strlen(text));
1786+ FixupSpaceWidths(layout, text);
1787+
1788+ // Get the logical extents
1789+ PangoLayoutLine *line;
1790+ if (pango_layout_get_line_count(layout) != 1) {
1791+ printf("Warning: more than one line!\n");
1792+ }
1793+ line = pango_layout_get_line(layout, 0);
1794+
1795+ PangoRectangle rect;
1796+ pango_layout_line_get_extents(line, NULL, &rect);
1797+
1798+ float P2T;
1799+ P2T = mDeviceContext->DevUnitsToAppUnits();
1800+
1801+ aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
1802+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
1803+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
1804+
1805+ // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
1806+ //aDimensions.ascent, aDimensions.descent);
1807+
1808+ loser:
1809+ g_free(text);
1810+ g_object_unref(layout);
1811+
1812+ return rv;
1813+}
1814+
1815+nsresult
1816+nsFontMetricsPSPango::GetTextDimensions(const char* aString,
1817+ PRInt32 aLength,
1818+ PRInt32 aAvailWidth,
1819+ PRInt32* aBreaks,
1820+ PRInt32 aNumBreaks,
1821+ nsTextDimensions& aDimensions,
1822+ PRInt32& aNumCharsFit,
1823+ nsTextDimensions& aLastWordDimensions,
1824+ PRInt32* aFontID)
1825+{
1826+
1827+ return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
1828+ aNumBreaks, aDimensions, aNumCharsFit,
1829+ aLastWordDimensions);
1830+
1831+}
1832+
1833+nsresult
1834+nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString,
1835+ PRInt32 aLength,
1836+ PRInt32 aAvailWidth,
1837+ PRInt32* aBreaks,
1838+ PRInt32 aNumBreaks,
1839+ nsTextDimensions& aDimensions,
1840+ PRInt32& aNumCharsFit,
1841+ nsTextDimensions& aLastWordDimensions,
1842+ PRInt32* aFontID)
1843+{
1844+ nsresult rv = NS_OK;
1845+ PRInt32 curBreak = 0;
1846+ gchar *curChar;
1847+
1848+ PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
1849+
1850+ gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
1851+ NULL, NULL, NULL);
1852+
1853+ curChar = text;
1854+
1855+ if (!text) {
1856+#ifdef DEBUG
1857+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
1858+ DUMP_PRUNICHAR(aString, (PRUint32)aLength)
1859+#endif
1860+ rv = NS_ERROR_FAILURE;
1861+ goto loser;
1862+ }
1863+
1864+ // Covert the utf16 break offsets to utf8 break offsets
1865+ for (PRInt32 curOffset=0; curOffset < aLength;
1866+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1867+ if (aBreaks[curBreak] == curOffset) {
1868+ utf8Breaks[curBreak] = curChar - text;
1869+ curBreak++;
1870+ }
1871+
1872+ if (IS_HIGH_SURROGATE(aString[curOffset]))
1873+ curOffset++;
1874+ }
1875+
1876+ // Always catch the last break
1877+ utf8Breaks[curBreak] = curChar - text;
1878+
1879+#if 0
1880+ if (strlen(text) != aLength) {
1881+ printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
1882+ DUMP_PRUNICHAR(aString, aLength)
1883+ DUMP_PRUNICHAR(text, strlen(text))
1884+ for (PRInt32 i = 0; i < aNumBreaks; ++i) {
1885+ printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
1886+ }
1887+ }
1888+#endif
1889+
1890+ // We'll use curBreak to indicate which of the breaks end up being
1891+ // used for the break point for this line.
1892+ curBreak = 0;
1893+ rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
1894+ aNumBreaks, aDimensions, aNumCharsFit,
1895+ aLastWordDimensions);
1896+
1897+ // Figure out which of the breaks we ended up using to convert
1898+ // back to utf16 - start from the end.
1899+ for (PRInt32 i = aNumBreaks - 1; i >= 0; --i) {
1900+ if (utf8Breaks[i] == aNumCharsFit) {
1901+ // if (aNumCharsFit != aBreaks[i])
1902+ // printf("Fixing utf8 -> utf16 %d -> %d\n", aNumCharsFit, aBreaks[i]);
1903+ aNumCharsFit = aBreaks[i];
1904+ break;
1905+ }
1906+ }
1907+
1908+ loser:
1909+ if (text)
1910+ g_free(text);
1911+
1912+ delete[] utf8Breaks;
1913+
1914+ return rv;
1915+}
1916+
1917+typedef struct _nsPSPangoRenderer nsPSPangoRenderer;
1918+typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass;
1919+
1920+struct _nsPSPangoRenderer
1921+{
1922+ PangoRenderer parent_instance;
1923+ nsRenderingContextPS *psContext;
1924+ nsFontMetricsPSPango *psPangoFontMetrics;
1925+ float zoom;
1926+};
1927+
1928+struct _nsPSPangoRendererClass
1929+{
1930+ PangoRendererClass parent_class;
1931+};
1932+
1933+#define _PS_TYPE_PANGO_RENDERER (_ps_pango_renderer_get_type())
1934+#define _PS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
1935+#define _PS_IS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
1936+#define _PS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
1937+#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
1938+#define _PS_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
1939+
1940+G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
1941+
1942+static PangoRenderer *
1943+get_renderer (void)
1944+{
1945+ static PangoRenderer *renderer = NULL;
1946+
1947+ if (!renderer)
1948+ renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
1949+
1950+ return renderer;
1951+}
1952+
1953+static void
1954+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
1955+ PangoFont *font,
1956+ PangoGlyphString *glyphs,
1957+ int x,
1958+ int y);
1959+
1960+static void
1961+_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
1962+{
1963+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
1964+
1965+ renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
1966+}
1967+
1968+static void
1969+_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
1970+{
1971+}
1972+
1973+class nsPangoType1Generator : public nsPSFontGenerator {
1974+public:
1975+ nsPangoType1Generator();
1976+ ~nsPangoType1Generator();
1977+ nsresult Init(PangoFont *aFont);
1978+ void GeneratePSFont(FILE* aFile);
1979+
1980+protected:
1981+ PangoFont *mFont;
1982+};
1983+
1984+nsPangoType1Generator::nsPangoType1Generator()
1985+{
1986+}
1987+
1988+nsresult
1989+nsPangoType1Generator::Init(PangoFont *aFont)
1990+{
1991+ NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
1992+ mFont = aFont;
1993+ g_object_ref (mFont);
1994+ return NS_OK;
1995+}
1996+
1997+nsPangoType1Generator::~nsPangoType1Generator()
1998+{
1999+ g_object_unref (mFont);
2000+ mFont = nsnull;
2001+}
2002+
2003+void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
2004+{
2005+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
2006+
2007+ if (face == nsnull)
2008+ return;
2009+
2010+ int wmode = 0;
2011+ if (mGlyphSubset->Count())
2012+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
2013+
2014+ pango_fc_font_unlock_face ((PangoFcFont *) mFont);
2015+}
2016+
2017+typedef struct
2018+{
2019+ nsCString *FontNameBase;
2020+ nsCStringKey *key;
2021+ int font_size;
2022+} PSPangoFontData;
2023+
2024+static void
2025+ps_pango_font_data_destroy (PSPangoFontData *data)
2026+{
2027+ delete data->key;
2028+ delete data->FontNameBase;
2029+ g_free (data);
2030+}
2031+
2032+static void
2033+flattenName(nsCString& aString)
2034+{
2035+ nsCString::iterator start, end;
2036+ aString.BeginWriting(start);
2037+ aString.EndWriting(end);
2038+ while(start != end) {
2039+ if (*start == ' ')
2040+ *start= '_';
2041+ else if (*start == '(')
2042+ *start = '_';
2043+ else if (*start == ')')
2044+ *start = '_';
2045+ ++start;
2046+ }
2047+}
2048+
2049+static void
2050+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
2051+ PangoFont *font,
2052+ PangoGlyphString *glyphs,
2053+ int x,
2054+ int y)
2055+{
2056+ if (!glyphs->num_glyphs)
2057+ return;
2058+
2059+ static GQuark data_quark = 0;
2060+ if (!data_quark)
2061+ data_quark = g_quark_from_static_string ("ps-pango-font-data");
2062+
2063+ PSPangoFontData *data;
2064+ if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
2065+ {
2066+ data = g_new (PSPangoFontData, 1);
2067+
2068+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
2069+ if (face == nsnull)
2070+ return;
2071+ int wmode = 0;
2072+ data->FontNameBase = new nsCString ();
2073+ if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
2074+ g_free (data);
2075+ pango_fc_font_unlock_face ((PangoFcFont *) font);
2076+ return;
2077+ }
2078+ pango_fc_font_unlock_face ((PangoFcFont *) font);
2079+
2080+ PangoFontDescription *desc = pango_font_describe (font);
2081+ data->font_size = pango_font_description_get_size (desc);
2082+ pango_font_description_free (desc);
2083+
2084+ data->key = new nsCStringKey (*data->FontNameBase);
2085+
2086+ g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
2087+ }
2088+
2089+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
2090+ nsRenderingContextPS *aContext = ps_renderer->psContext;
2091+ nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
2092+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
2093+ nsPostScriptObj* psObj = aContext->GetPostScriptObj();
2094+ nsHashtable *psFGList = dc->GetPSFontGeneratorList();
2095+ g_return_if_fail (psFGList);
2096+ nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
2097+ if (!psFontGen) {
2098+ nsresult rv;
2099+ psFontGen = new nsPangoType1Generator;
2100+ g_return_if_fail (psFontGen);
2101+ rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
2102+ if (NS_FAILED(rv)) {
2103+ delete psFontGen;
2104+ return;
2105+ }
2106+ psFGList->Put(data->key, (void *) psFontGen);
2107+ }
2108+ nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
2109+
2110+ g_return_if_fail (aContext);
2111+ g_return_if_fail (psObj);
2112+
2113+ nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
2114+ nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
2115+ psObj->moveto(aX, aY);
2116+
2117+ PRInt32 currSubFont, prevSubFont = -1;
2118+ PRUint32 i;
2119+ PangoGlyphString gl;
2120+
2121+ gl.glyphs = glyphs->glyphs;
2122+ gl.num_glyphs = 0;
2123+ for (i = 0; i < glyphs->num_glyphs; ++i) {
2124+ currSubFont = psFontGen->AddToGlyphSubset(glyphs->glyphs[i].glyph >= 0x00ffffff ? 0 : glyphs->glyphs[i].glyph);
2125+ if (prevSubFont != currSubFont) {
2126+ if (prevSubFont != -1)
2127+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
2128+
2129+
2130+ psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
2131+ prevSubFont = currSubFont;
2132+ gl.glyphs = glyphs->glyphs + i;
2133+ gl.num_glyphs = 0;
2134+ }
2135+
2136+ gl.num_glyphs++;
2137+ }
2138+
2139+ if (prevSubFont != -1)
2140+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
2141+}
2142+
2143+static void
2144+draw_layout_line (int x, int y, PangoLayoutLine *line, nsFontMetricsPSPango *aPSPangoFontMetrics, nsRenderingContextPS *aContext)
2145+{
2146+ PangoRenderer *renderer = get_renderer ();
2147+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
2148+ ps_renderer->psContext = aContext;
2149+ ps_renderer->psPangoFontMetrics = aPSPangoFontMetrics;
2150+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, aPSPangoFontMetrics->GetDeviceContext());
2151+ ps_renderer->zoom = dc->DevUnitsToAppUnits();
2152+
2153+ pango_renderer_draw_layout_line (renderer, line,
2154+ NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
2155+ NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
2156+}
2157+
2158+nsresult
2159+nsFontMetricsPSPango::DrawString(const char *aString, PRUint32 aLength,
2160+ nscoord aX, nscoord aY,
2161+ const nscoord* aSpacing,
2162+ nsRenderingContextPS *aContext)
2163+{
2164+ PangoLayout *layout = pango_layout_new(mPangoContext);
2165+
2166+ pango_layout_set_text(layout, aString, aLength);
2167+ FixupSpaceWidths(layout, aString);
2168+
2169+ int x = aX;
2170+ int y = aY;
2171+
2172+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
2173+
2174+ PangoLayoutLine *line;
2175+ if (pango_layout_get_line_count(layout) != 1) {
2176+ printf("Warning: more than one line!\n");
2177+ }
2178+ line = pango_layout_get_line(layout, 0);
2179+
2180+ if (aSpacing && *aSpacing) {
2181+ DrawStringSlowly(aString, NULL, aLength, x, y, line, aSpacing, aContext);
2182+ }
2183+ else {
2184+ draw_layout_line (x, y, line, this, aContext);
2185+ }
2186+
2187+ g_object_unref(layout);
2188+
2189+ return NS_OK;
2190+}
2191+
2192+nsresult
2193+nsFontMetricsPSPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
2194+ nscoord aX, nscoord aY,
2195+ PRInt32 aFontID,
2196+ const nscoord* aSpacing,
2197+ nsRenderingContextPS *aContext)
2198+{
2199+ nsresult rv = NS_OK;
2200+ int x = aX;
2201+ int y = aY;
2202+
2203+ PangoLayout *layout = pango_layout_new(mPangoContext);
2204+
2205+ gchar *text = g_utf16_to_utf8(aString, aLength,
2206+ NULL, NULL, NULL);
2207+ if (!text) {
2208+#ifdef DEBUG
2209+ NS_WARNING("nsFontMetricsPSPango::DrawString invalid unicode to follow");
2210+ DUMP_PRUNICHAR(aString, aLength)
2211+#endif
2212+ rv = NS_ERROR_FAILURE;
2213+ goto loser;
2214+ }
2215+
2216+ pango_layout_set_text(layout, text, strlen(text));
2217+ FixupSpaceWidths(layout, text);
2218+
2219+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
2220+
2221+ PangoLayoutLine *line;
2222+ if (pango_layout_get_line_count(layout) != 1) {
2223+ printf("Warning: more than one line!\n");
2224+ }
2225+ line = pango_layout_get_line(layout, 0);
2226+
2227+ if (aSpacing && *aSpacing) {
2228+ DrawStringSlowly(text, aString, aLength, x, y, line, aSpacing, aContext);
2229+ }
2230+ else {
2231+ draw_layout_line (x, y, line, this, aContext);
2232+ }
2233+
2234+ loser:
2235+
2236+ g_free(text);
2237+ g_object_unref(layout);
2238+
2239+ return rv;
2240+}
2241+
2242+#ifdef MOZ_MATHML
2243+nsresult
2244+nsFontMetricsPSPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
2245+ nsBoundingMetrics &aBoundingMetrics)
2246+{
2247+ printf("GetBoundingMetrics (char *)\n");
2248+ return NS_ERROR_FAILURE;
2249+}
2250+
2251+nsresult
2252+nsFontMetricsPSPango::GetBoundingMetrics(const PRUnichar *aString,
2253+ PRUint32 aLength,
2254+ nsBoundingMetrics &aBoundingMetrics,
2255+ PRInt32 *aFontID)
2256+{
2257+ nsresult rv = NS_OK;
2258+ PangoLayout *layout = pango_layout_new(mPangoContext);
2259+
2260+ gchar *text = g_utf16_to_utf8(aString, aLength,
2261+ NULL, NULL, NULL);
2262+
2263+ if (!text) {
2264+#ifdef DEBUG
2265+ NS_WARNING("nsFontMetricsPSPango::GetBoundingMetrics invalid unicode to follow");
2266+ DUMP_PRUNICHAR(aString, aLength)
2267+#endif
2268+ aBoundingMetrics.leftBearing = 0;
2269+ aBoundingMetrics.rightBearing = 0;
2270+ aBoundingMetrics.width = 0;
2271+ aBoundingMetrics.ascent = 0;
2272+ aBoundingMetrics.descent = 0;
2273+
2274+ rv = NS_ERROR_FAILURE;
2275+ goto loser;
2276+ }
2277+
2278+ pango_layout_set_text(layout, text, -1);
2279+ FixupSpaceWidths(layout, text);
2280+
2281+ PangoLayoutLine *line;
2282+ if (pango_layout_get_line_count(layout) != 1) {
2283+ printf("Warning: more than one line!\n");
2284+ }
2285+ line = pango_layout_get_line(layout, 0);
2286+
2287+ // Get the ink and logical extents
2288+ PangoRectangle ink, logical;
2289+ pango_layout_line_get_extents(line, &ink, &logical);
2290+
2291+ float P2T;
2292+ P2T = mDeviceContext->DevUnitsToAppUnits();
2293+
2294+ aBoundingMetrics.leftBearing = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
2295+ aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
2296+ aBoundingMetrics.ascent = NSToCoordRound(PANGO_ASCENT(ink) * P2T / PANGO_SCALE);
2297+ aBoundingMetrics.descent = NSToCoordRound(PANGO_DESCENT(ink) * P2T / PANGO_SCALE);
2298+ aBoundingMetrics.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
2299+
2300+ loser:
2301+ g_free(text);
2302+ g_object_unref(layout);
2303+
2304+ return rv;
2305+}
2306+
2307+#endif /* MOZ_MATHML */
2308+
2309+nsresult
2310+nsFontMetricsPSPango::SetRightToLeftText(PRBool aIsRTL)
2311+{
2312+ if (aIsRTL) {
2313+ if (!mRTLPangoContext) {
2314+ mRTLPangoContext = get_context();
2315+ pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
2316+
2317+ pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
2318+ pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
2319+ }
2320+ mPangoContext = mRTLPangoContext;
2321+ }
2322+ else {
2323+ mPangoContext = mLTRPangoContext;
2324+ }
2325+
2326+ mIsRTL = aIsRTL;
2327+ return NS_OK;
2328+}
2329+
2330+nsresult
2331+nsFontMetricsPSPango::GetClusterInfo(const PRUnichar *aText,
2332+ PRUint32 aLength,
2333+ PRUint8 *aClusterStarts)
2334+{
2335+ nsresult rv = NS_OK;
2336+ PangoLogAttr *attrs = NULL;
2337+ gint n_attrs = 0;
2338+ PangoLayout *layout = pango_layout_new(mPangoContext);
2339+
2340+ // Convert the incoming UTF-16 to UTF-8
2341+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
2342+
2343+ if (!text) {
2344+#ifdef DEBUG
2345+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2346+ DUMP_PRUNICHAR(aText, aLength)
2347+#endif
2348+ rv = NS_ERROR_FAILURE;
2349+ goto loser;
2350+ }
2351+
2352+ // Set up the pango layout
2353+ pango_layout_set_text(layout, text, strlen(text));
2354+ FixupSpaceWidths(layout, text);
2355+
2356+ // Convert back to UTF-16 while filling in the cluster info
2357+ // structure.
2358+ pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
2359+
2360+ for (PRUint32 pos = 0; pos < aLength; pos++) {
2361+ if (IS_HIGH_SURROGATE(aText[pos])) {
2362+ aClusterStarts[pos] = 1;
2363+ pos++;
2364+ }
2365+ else {
2366+ aClusterStarts[pos] = attrs[pos].is_cursor_position;
2367+ }
2368+ }
2369+
2370+ loser:
2371+ if (attrs)
2372+ g_free(attrs);
2373+ if (text)
2374+ g_free(text);
2375+ if (layout)
2376+ g_object_unref(layout);
2377+
2378+ return rv;
2379+}
2380+
2381+PRInt32
2382+nsFontMetricsPSPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
2383+ nsPoint aPt)
2384+{
2385+ int trailing = 0;
2386+ int inx = 0;
2387+ const gchar *curChar;
2388+ PRInt32 retval = 0;
2389+
2390+ float f = mDeviceContext->AppUnitsToDevUnits();
2391+
2392+ PangoLayout *layout = pango_layout_new(mPangoContext);
2393+ PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
2394+ PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
2395+
2396+ // Convert the incoming UTF-16 to UTF-8
2397+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
2398+
2399+ if (!text) {
2400+#ifdef DEBUG
2401+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2402+ DUMP_PRUNICHAR(aText, aLength)
2403+#endif
2404+ retval = -1;
2405+ goto loser;
2406+ }
2407+
2408+ // Set up the pango layout
2409+ pango_layout_set_text(layout, text, strlen(text));
2410+ FixupSpaceWidths(layout, text);
2411+
2412+ pango_layout_xy_to_index(layout, localX, localY,
2413+ &inx, &trailing);
2414+
2415+ // Convert the index back to the utf-16 index
2416+ curChar = text;
2417+
2418+ for (PRUint32 curOffset=0; curOffset < aLength;
2419+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
2420+
2421+ // Check for a match before checking for a surrogate pair
2422+ if (curChar - text == inx) {
2423+ retval = curOffset;
2424+ break;
2425+ }
2426+
2427+ if (IS_HIGH_SURROGATE(aText[curOffset]))
2428+ curOffset++;
2429+ }
2430+
2431+ // If there was a trailing result, advance the index pointer the
2432+ // number of characters equal to the trailing result.
2433+ while (trailing) {
2434+ retval++;
2435+ // Yes, this can make aInx > length to indicate the end of the
2436+ // string.
2437+ if (retval < (PRInt32)aLength && IS_HIGH_SURROGATE(aText[retval]))
2438+ retval++;
2439+ trailing--;
2440+ }
2441+
2442+ loser:
2443+ if (text)
2444+ g_free(text);
2445+ if (layout)
2446+ g_object_unref(layout);
2447+
2448+ return retval;
2449+}
2450+
2451+nsresult
2452+nsFontMetricsPSPango::GetRangeWidth(const PRUnichar *aText,
2453+ PRUint32 aLength,
2454+ PRUint32 aStart,
2455+ PRUint32 aEnd,
2456+ PRUint32 &aWidth)
2457+{
2458+ nsresult rv = NS_OK;
2459+ PRUint32 utf8Start = 0;
2460+ PRUint32 utf8End = 0;
2461+
2462+ aWidth = 0;
2463+
2464+ // Convert the incoming UTF-16 to UTF-8
2465+ gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
2466+ gchar *curChar = text;
2467+
2468+ if (!text) {
2469+#ifdef DEBUG
2470+ NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2471+ DUMP_PRUNICHAR(aText, aLength)
2472+#endif
2473+ rv = NS_ERROR_FAILURE;
2474+ goto loser;
2475+ }
2476+
2477+ // Convert the utf16 offsets into utf8 offsets
2478+ for (PRUint32 curOffset = 0; curOffset < aLength;
2479+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
2480+
2481+ if (curOffset == aStart)
2482+ utf8Start = curChar - text;
2483+
2484+ if (curOffset == aEnd)
2485+ utf8End = curChar - text;
2486+
2487+ if (IS_HIGH_SURROGATE(aText[curOffset]))
2488+ curOffset++;
2489+ }
2490+
2491+ // Special case where the end index is the same as the length
2492+ if (aLength == aEnd)
2493+ utf8End = strlen(text);
2494+
2495+ rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
2496+
2497+ loser:
2498+ if (text)
2499+ g_free(text);
2500+
2501+ return rv;
2502+}
2503+
2504+nsresult
2505+nsFontMetricsPSPango::GetRangeWidth(const char *aText,
2506+ PRUint32 aLength,
2507+ PRUint32 aStart,
2508+ PRUint32 aEnd,
2509+ PRUint32 &aWidth)
2510+{
2511+ nsresult rv = NS_OK;
2512+ int *ranges = NULL;
2513+ int n_ranges = 0;
2514+ float f;
2515+
2516+ aWidth = 0;
2517+
2518+ PangoLayout *layout = pango_layout_new(mPangoContext);
2519+
2520+ if (!aText) {
2521+ rv = NS_ERROR_FAILURE;
2522+ goto loser;
2523+ }
2524+
2525+ pango_layout_set_text(layout, aText, aLength);
2526+ FixupSpaceWidths(layout, aText);
2527+
2528+ PangoLayoutLine *line;
2529+ if (pango_layout_get_line_count(layout) != 1) {
2530+ printf("Warning: more than one line!\n");
2531+ }
2532+ line = pango_layout_get_line(layout, 0);
2533+
2534+ pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
2535+
2536+ aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
2537+
2538+ f = mDeviceContext-> DevUnitsToAppUnits();
2539+ aWidth = nscoord(aWidth * f / PANGO_SCALE);
2540+
2541+ loser:
2542+ if (ranges)
2543+ g_free(ranges);
2544+ if (layout)
2545+ g_object_unref(layout);
2546+
2547+ return rv;
2548+}
2549+
2550+PRUint32
2551+nsFontMetricsPSPango::GetHints(void)
2552+{
2553+ return (NS_RENDERING_HINT_BIDI_REORDERING |
2554+ NS_RENDERING_HINT_ARABIC_SHAPING |
2555+ NS_RENDERING_HINT_FAST_MEASURE |
2556+ NS_RENDERING_HINT_REORDER_SPACED_TEXT |
2557+ NS_RENDERING_HINT_TEXT_CLUSTERS);
2558+}
2559+
2560+/* static */
2561+nsresult
2562+nsFontMetricsPSPango::FamilyExists(nsIDeviceContext *aDevice,
2563+ const nsString &aName)
2564+{
2565+ // fontconfig family name is always in UTF-8
2566+ NS_ConvertUTF16toUTF8 name(aName);
2567+
2568+ nsresult rv = NS_ERROR_FAILURE;
2569+ PangoContext *context = get_context();
2570+ PangoFontFamily **familyList;
2571+ int n;
2572+
2573+ pango_context_list_families(context, &familyList, &n);
2574+
2575+ for (int i=0; i < n; i++) {
2576+ const char *tmpname = pango_font_family_get_name(familyList[i]);
2577+ if (!Compare(nsDependentCString(tmpname), name,
2578+ nsCaseInsensitiveCStringComparator())) {
2579+ rv = NS_OK;
2580+ break;
2581+ }
2582+ }
2583+
2584+ g_free(familyList);
2585+ g_object_unref(context);
2586+
2587+ return rv;
2588+}
2589+
2590+// Private Methods
2591+
2592+nsresult
2593+nsFontMetricsPSPango::RealizeFont(void)
2594+{
2595+ nsCString familyList;
2596+ // Create and fill out the font description.
2597+ mPangoFontDesc = pango_font_description_new();
2598+
2599+ // Add CSS names - walk the list of fonts, adding the generic as
2600+ // the last font
2601+ for (int i=0; i < mFontList.Count(); ++i) {
2602+ // if this was a generic name, break out of the loop since we
2603+ // don't want to add it to the pattern yet
2604+ if (mFontIsGeneric[i])
2605+ break;;
2606+
2607+ nsCString *familyName = mFontList.CStringAt(i);
2608+ familyList.Append(familyName->get());
2609+ familyList.Append(',');
2610+ }
2611+
2612+ // If there's a generic add a pref for the generic if there's one
2613+ // set.
2614+ if (mGenericFont && !mFont.systemFont) {
2615+ nsCString name;
2616+ name += "font.name.";
2617+ name += mGenericFont->get();
2618+ name += ".";
2619+
2620+ nsString langGroup;
2621+ mLangGroup->ToString(langGroup);
2622+
2623+ name.AppendWithConversion(langGroup);
2624+
2625+ nsCOMPtr<nsIPref> pref;
2626+ pref = do_GetService(NS_PREF_CONTRACTID);
2627+ if (pref) {
2628+ nsresult rv;
2629+ nsXPIDLCString value;
2630+ rv = pref->GetCharPref(name.get(), getter_Copies(value));
2631+
2632+ // we ignore prefs that have three hypens since they are X
2633+ // style prefs.
2634+ if (NS_FFRECountHyphens(value) < 3) {
2635+ nsCString tmpstr;
2636+ tmpstr.Append(value);
2637+
2638+ familyList.Append(tmpstr);
2639+ familyList.Append(',');
2640+ }
2641+ }
2642+ }
2643+
2644+ // Add the generic if there is one.
2645+ if (mGenericFont && !mFont.systemFont) {
2646+ familyList.Append(mGenericFont->get());
2647+ familyList.Append(',');
2648+ }
2649+
2650+ // Set the family
2651+ pango_font_description_set_family(mPangoFontDesc,
2652+ familyList.get());
2653+
2654+ // Set the point size
2655+ pango_font_description_set_size(mPangoFontDesc,
2656+ (gint)(mPointSize * PANGO_SCALE));
2657+
2658+ // Set the style
2659+ pango_font_description_set_style(mPangoFontDesc,
2660+ CalculateStyle(mFont.style));
2661+
2662+ // Set the weight
2663+ pango_font_description_set_weight(mPangoFontDesc,
2664+ CalculateWeight(mFont.weight));
2665+
2666+ // Now that we have the font description set up, create the
2667+ // context.
2668+ mLTRPangoContext = get_context();
2669+ mPangoContext = mLTRPangoContext;
2670+
2671+ // Make sure to set the base direction to LTR - if layout needs to
2672+ // render RTL text it will use ::SetRightToLeftText()
2673+ pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
2674+
2675+ // Set the pango language now that we have a context
2676+ pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
2677+
2678+ // And attach the font description to this context
2679+ pango_context_set_font_description(mPangoContext, mPangoFontDesc);
2680+
2681+ return NS_OK;
2682+}
2683+
2684+/* static */
2685+PRBool
2686+nsFontMetricsPSPango::EnumFontCallback(const nsString &aFamily,
2687+ PRBool aIsGeneric, void *aData)
2688+{
2689+ NS_ConvertUTF16toUTF8 name(aFamily);
2690+
2691+ // The newest fontconfig does the full Unicode case folding so that
2692+ // we're being lazy here by calling |ToLowerCase| after converting
2693+ // to UTF-8 assuming that in virtually all cases, we just have to
2694+ // fold [A-Z]. (bug 223653).
2695+ ToLowerCase(name);
2696+ nsFontMetricsPSPango *metrics = (nsFontMetricsPSPango *)aData;
2697+ metrics->mFontList.AppendCString(name);
2698+ metrics->mFontIsGeneric.AppendElement((void *)aIsGeneric);
2699+ if (aIsGeneric) {
2700+ metrics->mGenericFont =
2701+ metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1);
2702+ return PR_FALSE; // stop processing
2703+ }
2704+
2705+ return PR_TRUE; // keep processing
2706+}
2707+
2708+/*
2709+ * This is only used when there's per-character spacing happening.
2710+ * Well, really it can be either line or character spacing but it's
2711+ * just turtles all the way down!
2712+ */
2713+
2714+void
2715+nsFontMetricsPSPango::DrawStringSlowly(const gchar *aText,
2716+ const PRUnichar *aOrigString,
2717+ PRUint32 aLength,
2718+ gint aX, gint aY,
2719+ PangoLayoutLine *aLine,
2720+ const nscoord *aSpacing,
2721+ nsRenderingContextPS *aContext)
2722+{
2723+ float app2dev;
2724+ app2dev = mDeviceContext->AppUnitsToDevUnits();
2725+ gint offset = 0;
2726+
2727+ /*
2728+ * We walk the list of glyphs returned in each layout run,
2729+ * matching up the glyphs with the characters in the source text.
2730+ * We use the aSpacing argument to figure out where to place those
2731+ * glyphs. It's important to note that since the string we're
2732+ * working with is in UTF-8 while the spacing argument assumes
2733+ * that offset will be part of the UTF-16 string. Logical
2734+ * attributes in pango are in byte offsets in the UTF-8 string, so
2735+ * we need to store the offsets based on the UTF-8 string.
2736+ */
2737+ nscoord *utf8spacing = new nscoord[strlen(aText)];
2738+
2739+ if (aOrigString) {
2740+ const gchar *curChar = aText;
2741+ bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
2742+
2743+ // Covert the utf16 spacing offsets to utf8 spacing offsets
2744+ for (PRUint32 curOffset=0; curOffset < aLength;
2745+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
2746+ utf8spacing[curChar - aText] = aSpacing[curOffset];
2747+
2748+ if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
2749+ curOffset++;
2750+ }
2751+ }
2752+ else {
2753+ memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
2754+ }
2755+
2756+ gint curRun = 0;
2757+
2758+ for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
2759+ tmpList = tmpList->next, curRun++) {
2760+ PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
2761+ gint tmpOffset = 0;
2762+
2763+ /* printf(" Rendering run %d: \"%s\"\n", curRun,
2764+ &aText[layoutRun->item->offset]); */
2765+
2766+ for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
2767+ /* printf("glyph %d offset %d orig width %d new width %d\n", i,
2768+ * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
2769+ * layoutRun->glyphs->glyphs[i].geometry.width,
2770+ * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
2771+ */
2772+ gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
2773+ * app2dev * PANGO_SCALE);
2774+ layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
2775+ tmpOffset += thisOffset;
2776+ }
2777+
2778+ /* printf(" rendering at X coord %d\n", aX + offset); */
2779+ offset += tmpOffset;
2780+ }
2781+
2782+ draw_layout_line (aX, aY, aLine, this, aContext);
2783+
2784+ delete[] utf8spacing;
2785+}
2786+
2787+nsresult
2788+nsFontMetricsPSPango::GetTextDimensionsInternal(const gchar* aString,
2789+ PRInt32 aLength,
2790+ PRInt32 aAvailWidth,
2791+ PRInt32* aBreaks,
2792+ PRInt32 aNumBreaks,
2793+ nsTextDimensions& aDimensions,
2794+ PRInt32& aNumCharsFit,
2795+ nsTextDimensions& aLastWordDimensions)
2796+{
2797+ NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
2798+
2799+ // If we need to back up this state represents the last place
2800+ // we could break. We can use this to avoid remeasuring text
2801+ PRInt32 prevBreakState_BreakIndex = -1; // not known
2802+ // (hasn't been computed)
2803+ nscoord prevBreakState_Width = 0; // accumulated width to this point
2804+
2805+ // Initialize OUT parameters
2806+ GetMaxAscent(aLastWordDimensions.ascent);
2807+ GetMaxDescent(aLastWordDimensions.descent);
2808+ aLastWordDimensions.width = -1;
2809+ aNumCharsFit = 0;
2810+
2811+ // Iterate each character in the string and determine which font to use
2812+ nscoord width = 0;
2813+ PRInt32 start = 0;
2814+ nscoord aveCharWidth;
2815+ GetAveCharWidth(aveCharWidth);
2816+
2817+ while (start < aLength) {
2818+ // Estimate how many characters will fit. Do that by
2819+ // diving the available space by the average character
2820+ // width. Make sure the estimated number of characters is
2821+ // at least 1
2822+ PRInt32 estimatedNumChars = 0;
2823+
2824+ if (aveCharWidth > 0)
2825+ estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
2826+
2827+ if (estimatedNumChars < 1)
2828+ estimatedNumChars = 1;
2829+
2830+ // Find the nearest break offset
2831+ PRInt32 estimatedBreakOffset = start + estimatedNumChars;
2832+ PRInt32 breakIndex;
2833+ nscoord numChars;
2834+
2835+ // Find the nearest place to break that is less than or equal to
2836+ // the estimated break offset
2837+ if (aLength <= estimatedBreakOffset) {
2838+ // All the characters should fit
2839+ numChars = aLength - start;
2840+ breakIndex = aNumBreaks - 1;
2841+ }
2842+ else {
2843+ breakIndex = prevBreakState_BreakIndex;
2844+ while (((breakIndex + 1) < aNumBreaks) &&
2845+ (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
2846+ ++breakIndex;
2847+ }
2848+
2849+ if (breakIndex == prevBreakState_BreakIndex) {
2850+ ++breakIndex; // make sure we advanced past the
2851+ // previous break index
2852+ }
2853+
2854+ numChars = aBreaks[breakIndex] - start;
2855+ }
2856+
2857+ // Measure the text
2858+ nscoord twWidth = 0;
2859+ if ((1 == numChars) && (aString[start] == ' '))
2860+ GetSpaceWidth(twWidth);
2861+ else if (numChars > 0)
2862+ GetWidth(&aString[start], numChars, twWidth);
2863+
2864+ // See if the text fits
2865+ PRBool textFits = (twWidth + width) <= aAvailWidth;
2866+
2867+ // If the text fits then update the width and the number of
2868+ // characters that fit
2869+ if (textFits) {
2870+ aNumCharsFit += numChars;
2871+ width += twWidth;
2872+ start += numChars;
2873+
2874+ // This is a good spot to back up to if we need to so remember
2875+ // this state
2876+ prevBreakState_BreakIndex = breakIndex;
2877+ prevBreakState_Width = width;
2878+ }
2879+ else {
2880+ // See if we can just back up to the previous saved
2881+ // state and not have to measure any text
2882+ if (prevBreakState_BreakIndex > 0) {
2883+ // If the previous break index is just before the
2884+ // current break index then we can use it
2885+ if (prevBreakState_BreakIndex == (breakIndex - 1)) {
2886+ aNumCharsFit = aBreaks[prevBreakState_BreakIndex];
2887+ width = prevBreakState_Width;
2888+ break;
2889+ }
2890+ }
2891+
2892+ // We can't just revert to the previous break state
2893+ if (0 == breakIndex) {
2894+ // There's no place to back up to, so even though
2895+ // the text doesn't fit return it anyway
2896+ aNumCharsFit += numChars;
2897+ width += twWidth;
2898+ break;
2899+ }
2900+
2901+ // Repeatedly back up until we get to where the text
2902+ // fits or we're all the way back to the first word
2903+ width += twWidth;
2904+ while ((breakIndex >= 1) && (width > aAvailWidth)) {
2905+ twWidth = 0;
2906+ start = aBreaks[breakIndex - 1];
2907+ numChars = aBreaks[breakIndex] - start;
2908+
2909+ if ((1 == numChars) && (aString[start] == ' '))
2910+ GetSpaceWidth(twWidth);
2911+ else if (numChars > 0)
2912+ GetWidth(&aString[start], numChars, twWidth);
2913+ width -= twWidth;
2914+ aNumCharsFit = start;
2915+ breakIndex--;
2916+ }
2917+ break;
2918+ }
2919+ }
2920+
2921+ aDimensions.width = width;
2922+ GetMaxAscent(aDimensions.ascent);
2923+ GetMaxDescent(aDimensions.descent);
2924+
2925+ /* printf("aDimensions %d %d %d aLastWordDimensions %d %d %d aNumCharsFit %d\n",
2926+ aDimensions.width, aDimensions.ascent, aDimensions.descent,
2927+ aLastWordDimensions.width, aLastWordDimensions.ascent, aLastWordDimensions.descent,
2928+ aNumCharsFit); */
2929+
2930+ return NS_OK;
2931+}
2932+
2933+void
2934+nsFontMetricsPSPango::FixupSpaceWidths (PangoLayout *aLayout,
2935+ const char *aString)
2936+{
2937+ PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
2938+
2939+ gint curRun = 0;
2940+
2941+ for (GSList *tmpList = line->runs; tmpList && tmpList->data;
2942+ tmpList = tmpList->next, curRun++) {
2943+ PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
2944+
2945+ for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
2946+ gint thisOffset = (gint)layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset;
2947+ if (aString[thisOffset] == ' ')
2948+ layoutRun->glyphs->glyphs[i].geometry.width = mPangoSpaceWidth;
2949+ }
2950+ }
2951+}
2952+
2953+/* static */
2954+PangoLanguage *
2955+GetPangoLanguage(nsIAtom *aLangGroup)
2956+{
2957+ // Find the FC lang group for this lang group
2958+ nsCAutoString cname;
2959+ aLangGroup->ToUTF8String(cname);
2960+
2961+ // see if the lang group needs to be translated from mozilla's
2962+ // internal mapping into fontconfig's
2963+ const MozGtkLangGroup *langGroup;
2964+ langGroup = NS_FindFCLangGroup(cname);
2965+
2966+ // if there's no lang group, just use the lang group as it was
2967+ // passed to us
2968+ //
2969+ // we're casting away the const here for the strings - should be
2970+ // safe.
2971+ if (!langGroup)
2972+ return pango_language_from_string(cname.get());
2973+ else if (langGroup->Lang)
2974+ return pango_language_from_string((char *) langGroup->Lang);
2975+
2976+ return pango_language_from_string("en");
2977+}
2978+
2979+/* static */
2980+void
2981+FreeGlobals(void)
2982+{
2983+}
2984+
2985+/* static */
2986+PangoStyle
2987+CalculateStyle(PRUint8 aStyle)
2988+{
2989+ switch(aStyle) {
2990+ case NS_FONT_STYLE_ITALIC:
2991+ return PANGO_STYLE_OBLIQUE;
2992+ break;
2993+ case NS_FONT_STYLE_OBLIQUE:
2994+ return PANGO_STYLE_OBLIQUE;
2995+ break;
2996+ }
2997+
2998+ return PANGO_STYLE_NORMAL;
2999+}
3000+
3001+/* static */
3002+PangoWeight
3003+CalculateWeight (PRUint16 aWeight)
3004+{
3005+ /*
3006+ * weights come in two parts crammed into one
3007+ * integer -- the "base" weight is weight / 100,
3008+ * the rest of the value is the "offset" from that
3009+ * weight -- the number of steps to move to adjust
3010+ * the weight in the list of supported font weights,
3011+ * this value can be negative or positive.
3012+ */
3013+ PRInt32 baseWeight = (aWeight + 50) / 100;
3014+ PRInt32 offset = aWeight - baseWeight * 100;
3015+
3016+ /* clip weights to range 0 to 9 */
3017+ if (baseWeight < 0)
3018+ baseWeight = 0;
3019+ if (baseWeight > 9)
3020+ baseWeight = 9;
3021+
3022+ /* Map from weight value to fcWeights index */
3023+ static int fcWeightLookup[10] = {
3024+ 0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
3025+ };
3026+
3027+ PRInt32 fcWeight = fcWeightLookup[baseWeight];
3028+
3029+ /*
3030+ * adjust by the offset value, make sure we stay inside the
3031+ * fcWeights table
3032+ */
3033+ fcWeight += offset;
3034+
3035+ if (fcWeight < 0)
3036+ fcWeight = 0;
3037+ if (fcWeight > 4)
3038+ fcWeight = 4;
3039+
3040+ /* Map to final PANGO_WEIGHT value */
3041+ static int fcWeights[5] = {
3042+ 349,
3043+ 499,
3044+ 649,
3045+ 749,
3046+ 999
3047+ };
3048+
3049+ return (PangoWeight)fcWeights[fcWeight];
3050+}
3051+
3052+/* static */
3053+nsresult
3054+EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric,
3055+ PRUint32* aCount, PRUnichar*** aResult)
3056+{
3057+ FcPattern *pat = NULL;
3058+ FcObjectSet *os = NULL;
3059+ FcFontSet *fs = NULL;
3060+ nsresult rv = NS_ERROR_FAILURE;
3061+
3062+ PRUnichar **array = NULL;
3063+ PRUint32 narray = 0;
3064+ PRInt32 serif = 0, sansSerif = 0, monospace = 0, nGenerics;
3065+
3066+ *aCount = 0;
3067+ *aResult = nsnull;
3068+
3069+ pat = FcPatternCreate();
3070+ if (!pat)
3071+ goto end;
3072+
3073+ os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, NULL);
3074+ if (!os)
3075+ goto end;
3076+
3077+ // take the pattern and add the lang group to it
3078+ if (aLangGroup)
3079+ NS_AddLangGroup(pat, aLangGroup);
3080+
3081+ // get the font list
3082+ fs = FcFontList(0, pat, os);
3083+
3084+ if (!fs)
3085+ goto end;
3086+
3087+ if (!fs->nfont) {
3088+ rv = NS_OK;
3089+ goto end;
3090+ }
3091+
3092+ // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
3093+ // "monospace", slightly different from CSS's 5.
3094+ if (!aGeneric)
3095+ serif = sansSerif = monospace = 1;
3096+ else if (!strcmp(aGeneric, "serif"))
3097+ serif = 1;
3098+ else if (!strcmp(aGeneric, "sans-serif"))
3099+ sansSerif = 1;
3100+ else if (!strcmp(aGeneric, "monospace"))
3101+ monospace = 1;
3102+ else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
3103+ serif = sansSerif = 1;
3104+ else
3105+ NS_NOTREACHED("unexpected generic family");
3106+ nGenerics = serif + sansSerif + monospace;
3107+
3108+ array = NS_STATIC_CAST(PRUnichar **,
3109+ nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
3110+ if (!array)
3111+ goto end;
3112+
3113+ if (serif) {
3114+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
3115+ if (!name)
3116+ goto end;
3117+ array[narray++] = name;
3118+ }
3119+
3120+ if (sansSerif) {
3121+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
3122+ if (!name)
3123+ goto end;
3124+ array[narray++] = name;
3125+ }
3126+
3127+ if (monospace) {
3128+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
3129+ if (!name)
3130+ goto end;
3131+ array[narray++] = name;
3132+ }
3133+
3134+ for (int i=0; i < fs->nfont; ++i) {
3135+ char *family;
3136+
3137+ // if there's no family, just move to the next iteration
3138+ if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
3139+ (FcChar8 **) &family) != FcResultMatch) {
3140+ continue;
3141+ }
3142+
3143+ // fontconfig always returns family names in UTF-8
3144+ PRUnichar* name = UTF8ToNewUnicode(nsDependentCString(family));
3145+
3146+ if (!name)
3147+ goto end;
3148+
3149+ array[narray++] = name;
3150+ }
3151+
3152+ NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
3153+ CompareFontNames, nsnull);
3154+
3155+ *aCount = narray;
3156+ if (narray)
3157+ *aResult = array;
3158+ else
3159+ nsMemory::Free(array);
3160+
3161+ rv = NS_OK;
3162+
3163+ end:
3164+ if (NS_FAILED(rv) && array) {
3165+ while (narray)
3166+ nsMemory::Free (array[--narray]);
3167+ nsMemory::Free (array);
3168+ }
3169+ if (pat)
3170+ FcPatternDestroy(pat);
3171+ if (os)
3172+ FcObjectSetDestroy(os);
3173+ if (fs)
3174+ FcFontSetDestroy(fs);
3175+
3176+ return rv;
3177+}
3178+
3179+/* static */
3180+int
3181+CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure)
3182+{
3183+ const PRUnichar* str1 = *((const PRUnichar**) aArg1);
3184+ const PRUnichar* str2 = *((const PRUnichar**) aArg2);
3185+
3186+ return nsCRT::strcmp(str1, str2);
3187+}
3188+
3189+
3190+// nsFontEnumeratorPango class
3191+
3192+nsFontEnumeratorPango::nsFontEnumeratorPango()
3193+{
3194+}
3195+
3196+NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator)
3197+
3198+NS_IMETHODIMP
3199+nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount,
3200+ PRUnichar ***aResult)
3201+{
3202+ NS_ENSURE_ARG_POINTER(aResult);
3203+ *aResult = nsnull;
3204+ NS_ENSURE_ARG_POINTER(aCount);
3205+ *aCount = 0;
3206+
3207+ return EnumFontsPango(nsnull, nsnull, aCount, aResult);
3208+}
3209+
3210+NS_IMETHODIMP
3211+nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup,
3212+ const char *aGeneric,
3213+ PRUint32 *aCount,
3214+ PRUnichar ***aResult)
3215+{
3216+ NS_ENSURE_ARG_POINTER(aResult);
3217+ *aResult = nsnull;
3218+ NS_ENSURE_ARG_POINTER(aCount);
3219+ *aCount = 0;
3220+
3221+ // aLangGroup=null or "" means any (i.e., don't care)
3222+ // aGeneric=null or "" means any (i.e, don't care)
3223+ nsCOMPtr<nsIAtom> langGroup;
3224+ if (aLangGroup && *aLangGroup)
3225+ langGroup = do_GetAtom(aLangGroup);
3226+ const char* generic = nsnull;
3227+ if (aGeneric && *aGeneric)
3228+ generic = aGeneric;
3229+
3230+ return EnumFontsPango(langGroup, generic, aCount, aResult);
3231+}
3232+
3233+NS_IMETHODIMP
3234+nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup,
3235+ PRBool *aResult)
3236+{
3237+ NS_ENSURE_ARG_POINTER(aResult);
3238+ *aResult = PR_FALSE;
3239+ NS_ENSURE_ARG_POINTER(aLangGroup);
3240+
3241+ *aResult = PR_TRUE; // always return true for now.
3242+ // Finish me - ftang
3243+ return NS_OK;
3244+}
3245+
3246+NS_IMETHODIMP
3247+nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup,
3248+ const char *aGeneric,
3249+ PRUnichar **aResult)
3250+{
3251+ NS_ENSURE_ARG_POINTER(aResult);
3252+ *aResult = nsnull;
3253+
3254+ // Have a look at nsFontEnumeratorXft::GetDefaultFont for some
3255+ // possible code for this function.
3256+
3257+ return NS_OK;
3258+}
3259+
3260+NS_IMETHODIMP
3261+nsFontEnumeratorPango::UpdateFontList(PRBool *_retval)
3262+{
3263+ *_retval = PR_FALSE; // always return false for now
3264+ return NS_OK;
3265+}
3266Index: gfx/src/ps/nsFontMetricsPSPango.h
3267===================================================================
3268RCS file: gfx/src/ps/nsFontMetricsPSPango.h
3269diff -N gfx/src/ps/nsFontMetricsPSPango.h
3270--- /dev/null 1 Jan 1970 00:00:00 -0000
3271+++ gfx/src/ps/nsFontMetricsPSPango.h 23 Oct 2006 17:37:13 -0000
3272@@ -0,0 +1,305 @@
3273+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3274+/* vim:expandtab:shiftwidth=4:tabstop=4:
3275+ */
3276+/* ***** BEGIN LICENSE BLOCK *****
3277+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3278+ *
3279+ * The contents of this file are subject to the Mozilla Public License Version
3280+ * 1.1 (the "License"); you may not use this file except in compliance with
3281+ * the License. You may obtain a copy of the License at
3282+ * http://www.mozilla.org/MPL/
3283+ *
3284+ * Software distributed under the License is distributed on an "AS IS" basis,
3285+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
3286+ * for the specific language governing rights and limitations under the
3287+ * License.
3288+ *
3289+ * The Original Code is mozilla.org code.
3290+ *
3291+ * The Initial Developer of the Original Code is
3292+ * Christopher Blizzard <blizzard@mozilla.org>.
3293+ * Portions created by the Initial Developer are Copyright (C) 2002
3294+ * the Initial Developer. All Rights Reserved.
3295+ *
3296+ * Contributor(s):
3297+ *
3298+ * Alternatively, the contents of this file may be used under the terms of
3299+ * either the GNU General Public License Version 2 or later (the "GPL"), or
3300+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
3301+ * in which case the provisions of the GPL or the LGPL are applicable instead
3302+ * of those above. If you wish to allow use of your version of this file only
3303+ * under the terms of either the GPL or the LGPL, and not to allow others to
3304+ * use your version of this file under the terms of the MPL, indicate your
3305+ * decision by deleting the provisions above and replace them with the notice
3306+ * and other provisions required by the GPL or the LGPL. If you do not delete
3307+ * the provisions above, a recipient may use your version of this file under
3308+ * the terms of any one of the MPL, the GPL or the LGPL.
3309+ *
3310+ * ***** END LICENSE BLOCK ***** */
3311+
3312+#ifndef nsFontMetricsPSPango_h__
3313+#define nsFontMetricsPSPango_h__
3314+
3315+#include "nsIFontMetrics.h"
3316+#include "nsIFontEnumerator.h"
3317+#include "nsCRT.h"
3318+#include "nsIAtom.h"
3319+#include "nsString.h"
3320+#include "nsVoidArray.h"
3321+#include "nsFontMetricsPS.h"
3322+
3323+#include <pango/pango.h>
3324+
3325+class nsRenderingContextPS;
3326+class nsIDrawingSurface;
3327+
3328+class nsFontMetricsPSPango : public nsFontMetricsPS
3329+{
3330+public:
3331+ nsFontMetricsPSPango();
3332+ virtual ~nsFontMetricsPSPango();
3333+
3334+ NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
3335+
3336+ // nsISupports
3337+ NS_DECL_ISUPPORTS
3338+
3339+ // nsIFontMetrics
3340+ NS_IMETHOD Init (const nsFont& aFont, nsIAtom* aLangGroup,
3341+ nsIDeviceContext *aContext);
3342+ NS_IMETHOD Destroy();
3343+ NS_IMETHOD GetLangGroup (nsIAtom** aLangGroup);
3344+ NS_IMETHOD GetFontHandle (nsFontHandle &aHandle);
3345+
3346+ NS_IMETHOD GetXHeight (nscoord& aResult)
3347+ { aResult = mXHeight; return NS_OK; };
3348+
3349+ NS_IMETHOD GetSuperscriptOffset (nscoord& aResult)
3350+ { aResult = mSuperscriptOffset;
3351+ return NS_OK; };
3352+
3353+ NS_IMETHOD GetSubscriptOffset (nscoord& aResult)
3354+ { aResult = mSubscriptOffset;
3355+ return NS_OK; };
3356+
3357+ NS_IMETHOD GetStrikeout (nscoord& aOffset, nscoord& aSize)
3358+ { aOffset = mStrikeoutOffset;
3359+ aSize = mStrikeoutSize;
3360+ return NS_OK; };
3361+
3362+ NS_IMETHOD GetUnderline (nscoord& aOffset, nscoord& aSize)
3363+ { aOffset = mUnderlineOffset;
3364+ aSize = mUnderlineSize;
3365+ return NS_OK; };
3366+
3367+ NS_IMETHOD GetHeight (nscoord &aHeight)
3368+ { aHeight = mMaxHeight;
3369+ return NS_OK; };
3370+
3371+ NS_IMETHOD GetNormalLineHeight (nscoord &aHeight)
3372+ { aHeight = mEmHeight + mLeading;
3373+ return NS_OK; };
3374+
3375+ NS_IMETHOD GetLeading (nscoord &aLeading)
3376+ { aLeading = mLeading;
3377+ return NS_OK; };
3378+
3379+ NS_IMETHOD GetEmHeight (nscoord &aHeight)
3380+ { aHeight = mEmHeight;
3381+ return NS_OK; };
3382+
3383+ NS_IMETHOD GetEmAscent (nscoord &aAscent)
3384+ { aAscent = mEmAscent;
3385+ return NS_OK; };
3386+
3387+ NS_IMETHOD GetEmDescent (nscoord &aDescent)
3388+ { aDescent = mEmDescent;
3389+ return NS_OK; };
3390+
3391+ NS_IMETHOD GetMaxHeight (nscoord &aHeight)
3392+ { aHeight = mMaxHeight;
3393+ return NS_OK; };
3394+
3395+ NS_IMETHOD GetMaxAscent (nscoord &aAscent)
3396+ { aAscent = mMaxAscent;
3397+ return NS_OK; };
3398+
3399+ NS_IMETHOD GetMaxDescent (nscoord &aDescent)
3400+ { aDescent = mMaxDescent;
3401+ return NS_OK; };
3402+
3403+ NS_IMETHOD GetMaxAdvance (nscoord &aAdvance)
3404+ { aAdvance = mMaxAdvance;
3405+ return NS_OK; };
3406+
3407+ NS_IMETHOD GetSpaceWidth (nscoord &aSpaceCharWidth)
3408+ { aSpaceCharWidth = mSpaceWidth;
3409+ return NS_OK; };
3410+
3411+ NS_IMETHOD GetAveCharWidth (nscoord &aAveCharWidth)
3412+ { aAveCharWidth = mAveCharWidth;
3413+ return NS_OK; };
3414+
3415+ // nsIFontMetricsPS (calls from the font rendering layer)
3416+ NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
3417+ NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
3418+
3419+ NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
3420+ nscoord& aWidth);
3421+ NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
3422+ nscoord& aWidth);
3423+
3424+ NS_IMETHOD GetTextDimensions(const char* aString,
3425+ PRUint32 aLength,
3426+ nsTextDimensions& aDimensions);
3427+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
3428+ PRUint32 aLength,
3429+ nsTextDimensions& aDimensions,
3430+ PRInt32* aFontID);
3431+ NS_IMETHOD GetTextDimensions(const char* aString,
3432+ PRInt32 aLength,
3433+ PRInt32 aAvailWidth,
3434+ PRInt32* aBreaks,
3435+ PRInt32 aNumBreaks,
3436+ nsTextDimensions& aDimensions,
3437+ PRInt32& aNumCharsFit,
3438+ nsTextDimensions& aLastWordDimensions,
3439+ PRInt32* aFontID);
3440+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
3441+ PRInt32 aLength,
3442+ PRInt32 aAvailWidth,
3443+ PRInt32* aBreaks,
3444+ PRInt32 aNumBreaks,
3445+ nsTextDimensions& aDimensions,
3446+ PRInt32& aNumCharsFit,
3447+ nsTextDimensions& aLastWordDimensions,
3448+ PRInt32* aFontID);
3449+
3450+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
3451+ nscoord aX, nscoord aY,
3452+ const nscoord* aSpacing,
3453+ nsRenderingContextPS *aContext);
3454+ NS_IMETHOD DrawString(const PRUnichar* aString, PRUint32 aLength,
3455+ nscoord aX, nscoord aY,
3456+ PRInt32 aFontID,
3457+ const nscoord* aSpacing,
3458+ nsRenderingContextPS *aContext);
3459+
3460+#ifdef MOZ_MATHML
3461+ NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
3462+ nsBoundingMetrics &aBoundingMetrics);
3463+ NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString,
3464+ PRUint32 aLength,
3465+ nsBoundingMetrics &aBoundingMetrics,
3466+ PRInt32 *aFontID);
3467+#endif /* MOZ_MATHML */
3468+
3469+ NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
3470+
3471+ NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
3472+ PRUint32 aLength,
3473+ PRUint8 *aClusterStarts);
3474+
3475+ virtual PRInt32 GetPosition(const PRUnichar *aText,
3476+ PRUint32 aLength,
3477+ nsPoint aPt);
3478+
3479+ NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
3480+ PRUint32 aLength,
3481+ PRUint32 aStart,
3482+ PRUint32 aEnd,
3483+ PRUint32 &aWidth);
3484+
3485+ NS_IMETHOD GetRangeWidth(const char *aText,
3486+ PRUint32 aLength,
3487+ PRUint32 aStart,
3488+ PRUint32 aEnd,
3489+ PRUint32 &aWidth);
3490+
3491+ // get hints for the font
3492+ virtual PRUint32 GetHints (void);
3493+
3494+ // drawing surface methods
3495+ static nsresult FamilyExists (nsIDeviceContext *aDevice,
3496+ const nsString &aName);
3497+
3498+ inline nsIDeviceContext *GetDeviceContext() { return mDeviceContext; }
3499+
3500+private:
3501+
3502+ // generic font metrics class bits
3503+ nsCStringArray mFontList;
3504+ nsAutoVoidArray mFontIsGeneric;
3505+
3506+ nsIDeviceContext *mDeviceContext;
3507+ nsCOMPtr<nsIAtom> mLangGroup;
3508+ nsCString *mGenericFont;
3509+ float mPointSize;
3510+
3511+ nsCAutoString mDefaultFont;
3512+
3513+ // Pango-related items
3514+ PangoFontDescription *mPangoFontDesc;
3515+ PangoContext *mPangoContext;
3516+ PangoContext *mLTRPangoContext;
3517+ PangoContext *mRTLPangoContext;
3518+ PangoAttrList *mPangoAttrList;
3519+ PRBool mIsRTL;
3520+
3521+ // Cached font metrics
3522+ nscoord mXHeight;
3523+ nscoord mSuperscriptOffset;
3524+ nscoord mSubscriptOffset;
3525+ nscoord mStrikeoutOffset;
3526+ nscoord mStrikeoutSize;
3527+ nscoord mUnderlineOffset;
3528+ nscoord mUnderlineSize;
3529+ nscoord mMaxHeight;
3530+ nscoord mLeading;
3531+ nscoord mEmHeight;
3532+ nscoord mEmAscent;
3533+ nscoord mEmDescent;
3534+ nscoord mMaxAscent;
3535+ nscoord mMaxDescent;
3536+ nscoord mMaxAdvance;
3537+ nscoord mSpaceWidth;
3538+ nscoord mPangoSpaceWidth;
3539+ nscoord mAveCharWidth;
3540+
3541+ // Private methods
3542+ nsresult RealizeFont(void);
3543+ nsresult CacheFontMetrics(void);
3544+
3545+ static PRBool EnumFontCallback(const nsString &aFamily,
3546+ PRBool aIsGeneric, void *aData);
3547+
3548+ void DrawStringSlowly(const gchar *aText,
3549+ const PRUnichar *aOrigString,
3550+ PRUint32 aLength,
3551+ gint aX, gint aY,
3552+ PangoLayoutLine *aLine,
3553+ const nscoord *aSpacing,
3554+ nsRenderingContextPS *aContext);
3555+
3556+ nsresult GetTextDimensionsInternal(const gchar* aString,
3557+ PRInt32 aLength,
3558+ PRInt32 aAvailWidth,
3559+ PRInt32* aBreaks,
3560+ PRInt32 aNumBreaks,
3561+ nsTextDimensions& aDimensions,
3562+ PRInt32& aNumCharsFit,
3563+ nsTextDimensions& aLastWordDimensions);
3564+
3565+ void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
3566+};
3567+
3568+class nsFontEnumeratorPango : public nsIFontEnumerator
3569+{
3570+public:
3571+ nsFontEnumeratorPango();
3572+ NS_DECL_ISUPPORTS
3573+ NS_DECL_NSIFONTENUMERATOR
3574+};
3575+
3576+#endif
3577+
3578Index: gfx/src/ps/nsPostScriptObj.cpp
3579===================================================================
3580RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.cpp,v
3581retrieving revision 1.124
3582diff -u -p -d -r1.124 nsPostScriptObj.cpp
3583--- gfx/src/ps/nsPostScriptObj.cpp 26 Jul 2005 15:54:18 -0000 1.124
3584+++ gfx/src/ps/nsPostScriptObj.cpp 23 Oct 2006 17:37:29 -0000
3585@@ -2061,31 +2061,74 @@ nsPostScriptObj::show(const PRUnichar* t
3586
3587 #if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3588 void
3589-nsPostScriptObj::show(const PRUnichar* aTxt, int aLen,
3590- const nsAFlatString& aCharList, PRUint16 aSubFontIdx)
3591+/*nsPostScriptObj::show(const PRUnichar* aTxt, int aLen,
3592+ const nsAFlatString& aCharList, PRUint16 aSubFontIdx) */
3593+nsPostScriptObj::show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset,
3594+ PRUint16 aSubFontIdx)
3595 {
3596- int i;
3597+ PRUint32 i;
3598 fputc('<', mScriptFP);
3599
3600- const PRUint16 subFontSize = nsPSFontGenerator::kSubFontSize;
3601+ for (i = 0; i < aGlyphs->Count(); i++) {
3602+ PRUint32 glyph = aGlyphs->ValueAt(i);
3603+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph));
3604+ }
3605
3606- // the character repertoire of a subfont (255 characters max)
3607- const nsAString& repertoire =
3608- Substring(aCharList, aSubFontIdx * subFontSize,
3609- PR_MIN(subFontSize,
3610- aCharList.Length() - aSubFontIdx * subFontSize));
3611+ fputs("> show\n", mScriptFP);
3612+}
3613+#endif
3614
3615- for (i = 0; i < aLen; i++) {
3616- // XXX This is a little inefficient, but printing is not perf. critical.
3617- NS_ASSERTION(repertoire.FindChar(aTxt[i]) != kNotFound,
3618- "character is not covered by this subfont");
3619-
3620- // Type 1 encoding vector has 256 slots, but the 0-th slot is
3621- // reserved for /.notdef so that we use the 1st through 255th slots
3622- // for actual characters (hence '+ 1')
3623- fprintf(mScriptFP, "%02x", repertoire.FindChar(aTxt[i]) + 1);
3624+#ifdef MOZ_ENABLE_PANGO
3625+void
3626+nsPostScriptObj::show(const PangoGlyphString *glyphs, float zoom,
3627+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx)
3628+{
3629+ PRUint32 i;
3630+ int horiz = 1;
3631+
3632+ if (glyphs->glyphs[0].geometry.x_offset || glyphs->glyphs[0].geometry.y_offset)
3633+ rmoveto (NSToCoordRound (zoom * glyphs->glyphs[0].geometry.x_offset / PANGO_SCALE),
3634+ NSToCoordRound (zoom * glyphs->glyphs[0].geometry.y_offset / PANGO_SCALE));
3635+
3636+ fputc('<', mScriptFP);
3637+
3638+ for (i = 0; i < glyphs->num_glyphs; i++) {
3639+ PRUint32 glyph = glyphs->glyphs[i].glyph;
3640+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph));
3641+ if (glyphs->glyphs[i].geometry.y_offset)
3642+ horiz = 0;
3643+ }
3644+
3645+ if (horiz) {
3646+ fputs(">\n[", mScriptFP);
3647+ for (i = 1; i < glyphs->num_glyphs; i++) {
3648+ fprintf(mScriptFP, "%d ",
3649+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.x_offset
3650+ + glyphs->glyphs[i-1].geometry.width
3651+ - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE));
3652+ }
3653+ fprintf(mScriptFP, "%d",
3654+ NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width
3655+ - glyphs->glyphs[i-1].geometry.x_offset
3656+ - glyphs->glyphs[ 0].geometry.x_offset) / PANGO_SCALE));
3657+ fputs("] xshow\n", mScriptFP);
3658+ } else {
3659+ fputs(">\n[", mScriptFP);
3660+ for (i = 1; i < glyphs->num_glyphs; i++) {
3661+ fprintf(mScriptFP, "%d %d ",
3662+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.x_offset
3663+ + glyphs->glyphs[i-1].geometry.width
3664+ - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE),
3665+ NSToCoordRound (zoom * (+ glyphs->glyphs[i ].geometry.y_offset
3666+ - glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE));
3667+ }
3668+ fprintf(mScriptFP, "%d %d",
3669+ NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width
3670+ - glyphs->glyphs[i-1].geometry.x_offset
3671+ - glyphs->glyphs[ 0].geometry.x_offset) / PANGO_SCALE),
3672+ NSToCoordRound (zoom * (- glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE));
3673+ fputs("] xyshow\n", mScriptFP);
3674 }
3675- fputs("> show\n", mScriptFP);
3676 }
3677 #endif
3678
3679@@ -2101,6 +2144,16 @@ nsPostScriptObj::moveto(nscoord x, nscoo
3680
3681 /** ---------------------------------------------------
3682 * See documentation in nsPostScriptObj.h
3683+ * @update 10/20/06 behdad
3684+ */
3685+void
3686+nsPostScriptObj::rmoveto(nscoord x, nscoord y)
3687+{
3688+ fprintf(mScriptFP, "%d %d rmoveto\n", x, y);
3689+}
3690+
3691+/** ---------------------------------------------------
3692+ * See documentation in nsPostScriptObj.h
3693 * @update 2/1/99 dwc
3694 */
3695 void
3696Index: gfx/src/ps/nsPostScriptObj.h
3697===================================================================
3698RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.h,v
3699retrieving revision 1.47
3700diff -u -p -d -r1.47 nsPostScriptObj.h
3701--- gfx/src/ps/nsPostScriptObj.h 8 May 2005 15:01:20 -0000 1.47
3702+++ gfx/src/ps/nsPostScriptObj.h 23 Oct 2006 17:37:30 -0000
3703@@ -57,9 +57,15 @@
3704 #include "nsIPersistentProperties2.h"
3705 #include "nsTempfilePS.h"
3706 #include "nsEPSObjectPS.h"
3707+#ifdef MOZ_ENABLE_PANGO
3708+#include <pango/pango.h>
3709+#endif
3710+
3711
3712+class nsPSFontGenerator;
3713 class nsIImage;
3714 class nsIAtom;
3715+class nsValueArray;
3716 #endif
3717
3718 #include <stdio.h>
3719@@ -217,6 +223,14 @@ public:
3720 */
3721 void moveto(nscoord aX, nscoord aY);
3722 /** ---------------------------------------------------
3723+ * Move relative to the current point
3724+ * @update 10/20/2006 behdad
3725+ * @param aX X coordinate
3726+ * aY Y coordinate
3727+ * @return VOID
3728+ */
3729+ void rmoveto(nscoord aX, nscoord aY);
3730+ /** ---------------------------------------------------
3731 * Add a line to the current path, from the current point
3732 * to the specified point.
3733 * @update 9/30/2003
3734@@ -346,12 +360,24 @@ public:
3735 */
3736 void show(const PRUnichar* aText, int aLen, const char *aAlign, int aType);
3737 /** ---------------------------------------------------
3738- * This version takes a PRUnichar string, a font subset string
3739- * for freetype printing and a subfont index
3740+ * This version of show takes an array of glyphs, subfont and subfont index
3741+ * to render and is used for freetype and xft printing.
3742 * @update 2/15/2005 jshin@mailaps.org
3743+ * @update 6/7/2005 blizzard@mozilla.org
3744 */
3745- void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList,
3746+ void show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset,
3747 PRUint16 aSubFontIdx);
3748+ /*void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList,
3749+ PRUint16 aSubFontIdx); */
3750+#ifdef MOZ_ENABLE_PANGO
3751+ /** ---------------------------------------------------
3752+ * This version of show takes a pango glyph string, subfont and subfont index
3753+ * to render and is used for pango printing.
3754+ * @update 10/20/2006 behdad@behdad.org
3755+ */
3756+ void show(const PangoGlyphString *glyphs, float zoom,
3757+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx);
3758+#endif
3759 /** ---------------------------------------------------
3760 * set the clipping path to the current path using the winding rule
3761 * @update 2/1/99 dwc
3762Index: gfx/src/ps/nsRenderingContextPS.cpp
3763===================================================================
3764RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.cpp,v
3765retrieving revision 1.83
3766diff -u -p -d -r1.83 nsRenderingContextPS.cpp
3767--- gfx/src/ps/nsRenderingContextPS.cpp 4 Mar 2005 07:39:27 -0000 1.83
3768+++ gfx/src/ps/nsRenderingContextPS.cpp 23 Oct 2006 17:37:31 -0000
3769@@ -251,6 +251,8 @@ nsRenderingContextPS :: GetDrawingSurfac
3770 NS_IMETHODIMP
3771 nsRenderingContextPS :: GetHints(PRUint32& aResult)
3772 {
3773+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3774+ aResult = metrics->GetHints ();
3775 return NS_OK;
3776 }
3777
3778@@ -1006,8 +1008,11 @@ nsRenderingContextPS::GetTextDimensions(
3779 nsTextDimensions& aLastWordDimensions,
3780 PRInt32* aFontID)
3781 {
3782- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions");
3783- return NS_ERROR_NOT_IMPLEMENTED;
3784+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
3785+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3786+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3787+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
3788+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
3789 }
3790
3791 NS_IMETHODIMP
3792@@ -1021,43 +1026,31 @@ nsRenderingContextPS::GetTextDimensions(
3793 nsTextDimensions& aLastWordDimensions,
3794 PRInt32* aFontID)
3795 {
3796- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions");
3797- return NS_ERROR_NOT_IMPLEMENTED;
3798+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
3799+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3800+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3801+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
3802+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
3803 }
3804
3805 NS_IMETHODIMP
3806 nsRenderingContextPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
3807 nsTextDimensions& aDimensions)
3808 {
3809- nsresult rv = NS_ERROR_FAILURE;
3810-
3811- if (mFontMetrics) {
3812- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3813- metrics->GetStringWidth(aString, aDimensions.width, aLength);
3814- metrics->GetMaxAscent(aDimensions.ascent);
3815- metrics->GetMaxDescent(aDimensions.descent);
3816- rv = NS_OK;
3817- }
3818-
3819- return rv;
3820+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
3821+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3822+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3823+ return metrics->GetTextDimensions (aString, aLength, aDimensions);
3824 }
3825
3826 NS_IMETHODIMP
3827 nsRenderingContextPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
3828 nsTextDimensions& aDimensions, PRInt32* aFontID)
3829 {
3830- nsresult rv = NS_ERROR_FAILURE;
3831-
3832- if (mFontMetrics) {
3833- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3834- metrics->GetStringWidth(aString, aDimensions.width, aLength);
3835- //XXX temporary - bug 96609
3836- metrics->GetMaxAscent(aDimensions.ascent);
3837- metrics->GetMaxDescent(aDimensions.descent);
3838- rv = NS_OK;
3839- }
3840-
3841- return rv;
3842+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
3843+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3844+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3845+ return metrics->GetTextDimensions (aString, aLength, aDimensions, aFontID);
3846 }
3847
3848 /** ---------------------------------------------------
3849@@ -1073,47 +1066,7 @@ nsRenderingContextPS :: DrawString(const
3850
3851 nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3852 NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3853-
3854- // When FT2 printing is enabled, we don't need to set langgroup
3855-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3856- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) {
3857-#endif
3858- nsCOMPtr<nsIAtom> langGroup;
3859- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
3860- mPSObj->setlanggroup(langGroup);
3861-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3862- }
3863-#endif
3864-
3865- if (aLength == 0)
3866- return NS_OK;
3867- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
3868- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
3869- fontPS->SetupFont(this);
3870-
3871- PRUint32 i, start = 0;
3872- for (i=0; i<aLength; i++) {
3873- nsFontPS* fontThisChar;
3874- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics);
3875- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
3876- if (fontThisChar != fontPS) {
3877- // draw text up to this point
3878- aX += DrawString(aString+start, i-start, aX, aY, fontPS,
3879- aSpacing?aSpacing+start:nsnull);
3880- start = i;
3881-
3882- // setup for following text
3883- fontPS = fontThisChar;
3884- fontPS->SetupFont(this);
3885- }
3886- }
3887-
3888- // draw the last part
3889- if (aLength-start)
3890- DrawString(aString+start, aLength-start, aX, aY, fontPS,
3891- aSpacing?aSpacing+start:nsnull);
3892-
3893- return NS_OK;
3894+ return metrics->DrawString (aString, aLength, aX, aY, aSpacing, this);
3895 }
3896
3897 /** ---------------------------------------------------
3898@@ -1129,110 +1082,7 @@ nsRenderingContextPS :: DrawString(const
3899
3900 nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3901 NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
3902-
3903-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3904- // When FT2 printing is enabled, we don't need to set langgroup
3905- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) {
3906-#endif
3907- nsCOMPtr<nsIAtom> langGroup = nsnull;
3908- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
3909- mPSObj->setlanggroup(langGroup);
3910-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3911- }
3912-#endif
3913-
3914- /* build up conversion table */
3915- mPSObj->preshow(aString, aLength);
3916-
3917- if (aLength == 0)
3918- return NS_OK;
3919- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
3920- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
3921- fontPS->SetupFont(this);
3922-
3923- PRUint32 i, start = 0;
3924- for (i=0; i<aLength; i++) {
3925- nsFontPS* fontThisChar;
3926- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics);
3927- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
3928- if (fontThisChar != fontPS) {
3929- // draw text up to this point
3930- aX += DrawString(aString+start, i-start, aX, aY, fontPS,
3931- aSpacing?aSpacing+start:nsnull);
3932- start = i;
3933-
3934- // setup for following text
3935- fontPS = fontThisChar;
3936- fontPS->SetupFont(this);
3937- }
3938- }
3939-
3940- // draw the last part
3941- if (aLength-start)
3942- DrawString(aString+start, aLength-start, aX, aY, fontPS,
3943- aSpacing?aSpacing+start:nsnull);
3944-
3945- return NS_OK;
3946-}
3947-
3948-PRInt32
3949-nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength,
3950- nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
3951- const nscoord* aSpacing)
3952-{
3953- nscoord width = 0;
3954- PRInt32 x = aX;
3955- PRInt32 y = aY;
3956-
3957- PRInt32 dxMem[500];
3958- PRInt32* dx0 = 0;
3959- if (aSpacing) {
3960- dx0 = dxMem;
3961- if (aLength > 500) {
3962- dx0 = new PRInt32[aLength];
3963- NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
3964- }
3965- mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0);
3966- }
3967-
3968- mTranMatrix->TransformCoord(&x, &y);
3969- width = aFontPS->DrawString(this, x, y, aString, aLength);
3970-
3971- if ((aSpacing) && (dx0 != dxMem)) {
3972- delete [] dx0;
3973- }
3974-
3975- return width;
3976-}
3977-
3978-
3979-PRInt32
3980-nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength,
3981- nscoord aX, nscoord aY, nsFontPS* aFontPS,
3982- const nscoord* aSpacing)
3983-{
3984- nscoord width = 0;
3985- PRInt32 x = aX;
3986- PRInt32 y = aY;
3987-
3988- if (aSpacing) {
3989- // Slow, but accurate rendering
3990- const PRUnichar* end = aString + aLength;
3991- while (aString < end){
3992- x = aX;
3993- y = aY;
3994- mTranMatrix->TransformCoord(&x, &y);
3995- aFontPS->DrawString(this, x, y, aString, 1);
3996- aX += *aSpacing++;
3997- aString++;
3998- }
3999- width = aX;
4000- } else {
4001- mTranMatrix->TransformCoord(&x, &y);
4002- width = aFontPS->DrawString(this, x, y, aString, aLength);
4003- }
4004-
4005- return width;
4006+ return metrics->DrawString (aString, aLength, aX, aY, aFontID, aSpacing, this);
4007 }
4008
4009 /** ---------------------------------------------------
4010@@ -1346,8 +1196,10 @@ nsRenderingContextPS::GetBoundingMetrics
4011 PRUint32 aLength,
4012 nsBoundingMetrics& aBoundingMetrics)
4013 {
4014- // Fill me up
4015- return NS_ERROR_NOT_IMPLEMENTED;
4016+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
4017+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
4018+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
4019+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics);
4020 }
4021
4022 /**
4023@@ -1359,8 +1211,10 @@ nsRenderingContextPS::GetBoundingMetrics
4024 nsBoundingMetrics& aBoundingMetrics,
4025 PRInt32* aFontID)
4026 {
4027- // Fill me up
4028- return NS_ERROR_NOT_IMPLEMENTED;
4029+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
4030+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
4031+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
4032+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics, aFontID);
4033 }
4034 #endif /* MOZ_MATHML */
4035
4036Index: gfx/src/ps/nsRenderingContextPS.h
4037===================================================================
4038RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.h,v
4039retrieving revision 1.49
4040diff -u -p -d -r1.49 nsRenderingContextPS.h
4041--- gfx/src/ps/nsRenderingContextPS.h 20 Sep 2004 06:46:16 -0000 1.49
4042+++ gfx/src/ps/nsRenderingContextPS.h 23 Oct 2006 17:37:35 -0000
4043@@ -154,6 +154,10 @@ public:
4044 NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
4045 nscoord& aWidth, PRInt32 *aFontID);
4046
4047+ nsTransform2D *GetTranMatrix() {
4048+ return mTranMatrix;
4049+ }
4050+
4051 NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
4052 nscoord aX, nscoord aY,
4053 const nscoord* aSpacing);
4054@@ -164,13 +168,6 @@ public:
4055 NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
4056 PRInt32 aFontID,
4057 const nscoord* aSpacing);
4058-protected:
4059- PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength,
4060- nscoord aX, nscoord aY, nsFontPS* aFontPS,
4061- const nscoord* aSpacing);
4062- PRInt32 DrawString(const char *aString, PRUint32 aLength,
4063- nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
4064- const nscoord* aSpacing);
4065 public:
4066
4067 NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
4068Index: gfx/src/ps/nsType1.cpp
4069===================================================================
4070RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.cpp,v
4071retrieving revision 1.5.8.1
4072diff -u -p -d -r1.5.8.1 nsType1.cpp
4073--- gfx/src/ps/nsType1.cpp 19 Oct 2005 08:16:22 -0000 1.5.8.1
4074+++ gfx/src/ps/nsType1.cpp 23 Oct 2006 17:37:39 -0000
4075@@ -73,8 +73,13 @@
4076 #include "nsIFreeType2.h"
4077 #include "nsServiceManagerUtils.h"
4078 #endif
4079+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4080+#include FT_TYPE1_TABLES_H
4081+#endif
4082 #include "nsPrintfCString.h"
4083 #include "nsAutoBuffer.h"
4084+#include "nsValueArray.h"
4085+#include "nsVoidArray.h"
4086
4087 #define HEXASCII_LINE_LEN 64
4088
4089@@ -113,7 +118,7 @@ static void encryptAndHexOut(FILE *aFile
4090 const char *aBuf, PRInt32 aLen = -1);
4091 static void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey,
4092 const char *aStr, PRUint32 aLen,
4093- PRUnichar aId);
4094+ const char *aGlyphName);
4095 static void flattenName(nsCString& aString);
4096
4097 /* thunk a short name for this function */
4098@@ -202,19 +207,30 @@ Type1EncryptString(unsigned char *aInBuf
4099 aOutBuf[i] = Type1Encrypt(aInBuf[i], &key);
4100 }
4101
4102+static FT_UShort
4103+get_upm (FT_Face face)
4104+{
4105+ FT_UShort upm = face->units_per_EM;
4106+
4107+ if (!upm)
4108+ upm = 1000; // bitmap font or something
4109+
4110+ return upm;
4111+}
4112+
4113 static PRBool
4114 sideWidthAndBearing(const FT_Vector *aEndPt, FT2PT1_info *aFti)
4115 {
4116 int aw = 0;
4117 int ah = 0;
4118- FT_UShort upm = aFti->face->units_per_EM;
4119+ FT_UShort upm = get_upm (aFti->face);
4120 FT_GlyphSlot slot;
4121 FT_Glyph glyph;
4122 FT_BBox bbox;
4123
4124 slot = aFti->face->glyph;
4125
4126-#ifdef MOZ_ENABLE_XFT
4127+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4128 FT_Error error = FT_Get_Glyph(slot, &glyph);
4129 if (error) {
4130 NS_ERROR("sideWidthAndBearing failed to get glyph");
4131@@ -256,7 +272,7 @@ static int
4132 moveto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
4133 {
4134 FT2PT1_info *fti = (FT2PT1_info *)aClosure;
4135- FT_UShort upm = fti->face->units_per_EM;
4136+ FT_UShort upm = get_upm (fti->face);
4137 PRBool rslt;
4138
4139 if (fti->elm_cnt == 0) {
4140@@ -293,7 +309,7 @@ static int
4141 lineto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
4142 {
4143 FT2PT1_info *fti = (FT2PT1_info *)aClosure;
4144- FT_UShort upm = fti->face->units_per_EM;
4145+ FT_UShort upm = get_upm (fti->face);
4146
4147 if (toCS(upm, aEndPt->x) == fti->cur_x) {
4148 fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
4149@@ -320,7 +336,7 @@ conicto(nsFT_CONST FT_Vector *aControlPt
4150 void *aClosure)
4151 {
4152 FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
4153- FT_UShort upm = ftinfo->face->units_per_EM;
4154+ FT_UShort upm = get_upm (ftinfo->face);
4155 double ctl_x, ctl_y;
4156 double cur_x, cur_y, x3, y3;
4157 FT_Vector aControlPt1, aControlPt2;
4158@@ -353,7 +369,7 @@ cubicto(nsFT_CONST FT_Vector *aControlPt
4159 nsFT_CONST FT_Vector *aEndPt, void *aClosure)
4160 {
4161 FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
4162- FT_UShort upm = ftinfo->face->units_per_EM;
4163+ FT_UShort upm = get_upm (ftinfo->face);
4164 double cur_x, cur_y, x1, y1, x2, y2, x3, y3;
4165
4166 cur_x = ftinfo->cur_x;
4167@@ -408,8 +424,55 @@ static FT_Outline_Funcs ft_outline_funcs
4168 0
4169 };
4170
4171+
4172+static int
4173+trace_bitmap_glyph (FT_GlyphSlot slot, FT2PT1_info *fti)
4174+{
4175+ unsigned char *row, *byte_ptr, byte;
4176+ int rows, cols;
4177+ int x, y, bit_mask;
4178+ int upm, x_off, y_off, x_mult, y_mult;
4179+
4180+ upm = get_upm (slot->face);
4181+ x_off = slot->bitmap_left;
4182+ y_off = slot->bitmap_top;
4183+ x_mult = upm / slot->face->size->metrics.x_ppem;
4184+ y_mult = upm / slot->face->size->metrics.y_ppem;
4185+
4186+ switch (slot->bitmap.pixel_mode) {
4187+ case FT_PIXEL_MODE_MONO:
4188+
4189+ for (y = 0, row = slot->bitmap.buffer, rows = slot->bitmap.rows; rows; row += slot->bitmap.pitch, rows--, y++) {
4190+ for (x = 0, byte_ptr = row, cols = (slot->bitmap.width + 7) / 8; cols; byte_ptr++, cols--) {
4191+ byte = *byte_ptr;
4192+ for (bit_mask = 128; bit_mask && x < slot->bitmap.width; bit_mask >>= 1, x++) {
4193+ if (byte & bit_mask) {
4194+ FT_Vector p;
4195+ p.x = x_mult * (x_off + x);
4196+ p.y = y_mult * (y_off - y);
4197+ moveto(&p, (void *) fti);
4198+ p.x += x_mult;
4199+ lineto(&p, (void *) fti);
4200+ p.y += y_mult;
4201+ lineto(&p, (void *) fti);
4202+ p.x -= x_mult;
4203+ lineto(&p, (void *) fti);
4204+ }
4205+ }
4206+ }
4207+ }
4208+ break;
4209+
4210+ default:
4211+ return 1;
4212+ }
4213+
4214+ return 0;
4215+}
4216+
4217+
4218 FT_Error
4219-#ifdef MOZ_ENABLE_XFT
4220+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4221 FT2GlyphToType1CharString(FT_Face aFace, PRUint32 aGlyphID,
4222 int aWmode, int aLenIV, unsigned char *aBuf)
4223 #else
4224@@ -423,7 +486,7 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4225 unsigned char *start = aBuf;
4226 FT2PT1_info fti;
4227
4228-#ifdef MOZ_ENABLE_XFT
4229+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4230 FT_Error error = FT_Load_Glyph(aFace, aGlyphID, flags);
4231 if (error) {
4232 NS_ERROR("failed to load aGlyphID");
4233@@ -438,11 +501,6 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4234 #endif
4235 slot = aFace->glyph;
4236
4237- if (slot->format != ft_glyph_format_outline) {
4238- NS_ERROR("aGlyphID is not an outline glyph");
4239- return 1;
4240- }
4241-
4242 #ifdef MOZ_ENABLE_FREETYPE2
4243 fti.ft2 = aFt2;
4244 #endif
4245@@ -456,18 +514,27 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4246 for (j=0; j< aLenIV; j++) {
4247 fti.len += ecsi(&fti.buf, 0);
4248 }
4249-#ifdef MOZ_ENABLE_XFT
4250- if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) {
4251- NS_ERROR("error decomposing aGlyphID");
4252- return 1;
4253- }
4254+
4255+ if (slot->format == ft_glyph_format_outline) {
4256+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4257+ if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) {
4258+ NS_ERROR("error decomposing aGlyphID");
4259+ return 1;
4260+ }
4261 #else
4262- rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
4263- if (NS_FAILED(rv)) {
4264- NS_ERROR("error decomposing aGlyphID");
4265- return 1;
4266- }
4267+ rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
4268+ if (NS_FAILED(rv)) {
4269+ NS_ERROR("error decomposing aGlyphID");
4270+ }
4271 #endif
4272+ } else if (slot->format == ft_glyph_format_bitmap) {
4273+ /* ok, it's a bitmap glyph. trace it! */
4274+ if (trace_bitmap_glyph (slot, &fti)) {
4275+ NS_ERROR("error tracing bitmap glyph");
4276+ }
4277+ } else {
4278+ NS_ERROR("aGlyphID has unhandled format");
4279+ }
4280
4281 if (fti.elm_cnt) {
4282 fti.len += csc(&fti.buf, T1_CLOSEPATH);
4283@@ -491,28 +558,52 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4284 }
4285
4286 static PRBool
4287-#ifdef MOZ_ENABLE_XFT
4288+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4289 outputType1SubFont(FT_Face aFace,
4290 #else
4291 outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
4292 #endif
4293- const nsAString &aCharIDs, const char *aFontName,
4294- int aWmode, int aLenIV, FILE *aFile);
4295+ nsValueArray *aGlyphs,
4296+ PRUint32 aOffset, PRUint32 aLen,
4297+ const char *aFontName,
4298+ int aWmode, int aLenIV, FILE *aFile);
4299
4300 nsresult
4301 FT2ToType1FontName(FT_Face aFace, int aWmode, nsCString& aFontName)
4302 {
4303+ // only hash the first 10 000 bytes of the font
4304+ int size = aFace->stream->size;
4305+ size = size > 10000 ? 10000 : size;
4306+
4307+ unsigned char *data;
4308+ if (aFace->stream->read) {
4309+ data = (unsigned char *) malloc (size);
4310+ aFace->stream->read (aFace->stream, 0, data, size);
4311+ } else {
4312+ data = aFace->stream->base;
4313+ }
4314+
4315+ unsigned int data_hash = 0;
4316+ int i;
4317+ for (i = 0; i < size; i++)
4318+ data_hash = (data_hash << 5) - data_hash + data[size];
4319+
4320+ if (aFace->stream->read)
4321+ free (data);
4322+
4323 aFontName = aFace->family_name;
4324 aFontName.AppendLiteral(".");
4325 aFontName += aFace->style_name;
4326- aFontName += nsPrintfCString(".%ld.%d", aFace->face_index, aWmode ? 1 : 0);
4327+ aFontName += nsPrintfCString(".%ld.%d.%lx.%x", aFace->face_index, aWmode ? 1 : 0,
4328+ (long) aFace->stream->size, data_hash);
4329 flattenName(aFontName);
4330+
4331 return NS_OK;
4332 }
4333
4334 // output a subsetted truetype font converted to multiple type 1 fonts
4335 PRBool
4336-FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset,
4337+FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset,
4338 int aWmode, FILE *aFile)
4339 {
4340 #ifdef MOZ_ENABLE_FREETYPE2
4341@@ -527,32 +618,35 @@ FT2SubsetToType1FontSet(FT_Face aFace, c
4342 nsCAutoString fontNameBase;
4343 FT2ToType1FontName(aFace, aWmode, fontNameBase);
4344 PRUint32 i = 0;
4345- for (; i <= aSubset.Length() / 255 ; i++) {
4346+ for (; i <= aGlyphSubset->Count() / 255 ; i++) {
4347 nsCAutoString fontName(fontNameBase);
4348 fontName.AppendLiteral(".Set");
4349 fontName.AppendInt(i);
4350-#ifdef MOZ_ENABLE_XFT
4351+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4352 outputType1SubFont(aFace,
4353 #else
4354 outputType1SubFont(ft2, aFace,
4355 #endif
4356- Substring(aSubset, i * 255, PR_MIN(255, aSubset.Length() - i * 255)),
4357- fontName.get(), aWmode, 4, aFile);
4358+ aGlyphSubset,
4359+ (i * 255), PR_MIN(255, aGlyphSubset->Count() - i * 255),
4360+ fontName.get(), aWmode, 4, aFile);
4361 }
4362 return PR_TRUE;
4363 }
4364
4365 // output a type 1 font (with 255 characters or fewer)
4366 static PRBool
4367-#ifdef MOZ_ENABLE_XFT
4368+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4369 outputType1SubFont(FT_Face aFace,
4370 #else
4371 outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
4372 #endif
4373- const nsAString& aCharIDs, const char *aFontName,
4374- int aWmode, int aLenIV, FILE *aFile)
4375+ nsValueArray *aGlyphs,
4376+ PRUint32 aOffset, PRUint32 aLen,
4377+ const char *aFontName,
4378+ int aWmode, int aLenIV, FILE *aFile)
4379 {
4380- FT_UShort upm = aFace->units_per_EM;
4381+ FT_UShort upm = get_upm (aFace);
4382
4383 fprintf(aFile, "%%%%BeginResource: font %s\n"
4384 "%%!PS-AdobeFont-1.0-3.0 %s 1.0\n"
4385@@ -573,9 +667,13 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
4386 toCS(upm, aFace->bbox.xMax),
4387 toCS(upm, aFace->bbox.yMax));
4388
4389- nsString charIDstr(aCharIDs);
4390- PRUint32 len = aCharIDs.Length();
4391-
4392+ nsValueArray glyphs(PR_UINT16_MAX);
4393+ nsCStringArray glyphnames(PR_UINT16_MAX);
4394+ glyphs = *aGlyphs;
4395+
4396+ PRUint32 len = aLen;
4397+ PRUint32 i;
4398+
4399 if (len < 10) {
4400 // Add a small set of characters to the subset of the user
4401 // defined font to produce to make sure the font ends up
4402@@ -584,25 +682,47 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
4403 // XXX : need to check if this is true of type 1 fonts as well.
4404 // I suspect it's only the case of CID-keyed fonts (type 9) we used to
4405 // generate.
4406- charIDstr.AppendLiteral("1234567890");
4407+ for (i = 1; i <= 10; i++) {
4408+ glyphs.AppendValue(i);
4409+ }
4410 len += 10;
4411 }
4412
4413- const PRUnichar *charIDs = charIDstr.get();
4414-
4415- PRUint32 i;
4416+ FT_Int has_glyph_name;
4417+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO)
4418+ has_glyph_name = FT_Has_PS_Glyph_Names(aFace);
4419+#else
4420+ has_glyph_name = aFt2->hasPSGlyphNames(aFace);
4421+#endif
4422
4423 // construct an Encoding vector : the 0th element
4424 // is /.notdef
4425- fputs("/Encoding [\n/.notdef\n", aFile);
4426- for (i = 0; i < len; ++i) {
4427- fprintf(aFile, "/uni%04X", charIDs[i]);
4428- if (i % 8 == 7) fputc('\n', aFile);
4429+ fputs("/Encoding [\n/.notdef", aFile);
4430+ for (i = aOffset; i < aOffset + aLen; ++i) {
4431+ nsCString name;
4432+ char buffer[256];
4433+
4434+ if (glyphs.ValueAt(i) == 0) {
4435+ name = "/.notdef";
4436+ } else if (!has_glyph_name ||
4437+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO)
4438+ FT_Get_Glyph_Name(aFace, glyphs.ValueAt(i), buffer, 255) != FT_Err_Ok
4439+#else
4440+ NS_FAILED(aFt2->getGlyphName(aFace, glyphs.ValueAt(i), buffer, 255))
4441+#endif
4442+ ) {
4443+ name = nsPrintfCString(256, "/idx%04X", glyphs.ValueAt(i));
4444+ } else {
4445+ name = nsPrintfCString(256, "/%s", buffer);
4446+ }
4447+ glyphnames.AppendCString(name);
4448+ fprintf(aFile, name.get());
4449+ if ((i-aOffset) % 8 == 6) fputc('\n', aFile);
4450 }
4451
4452- for (i = len; i < 255; ++i) {
4453+ for (i = PR_MAX (0, 255 - int(aLen)); i; --i) {
4454 fputs("/.notdef", aFile);
4455- if (i % 8 == 7) fputc('\n', aFile);
4456+ if (i % 8 == 1) fputc('\n', aFile);
4457 }
4458 fputs("] def\n", aFile);
4459
4460@@ -630,23 +750,21 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
4461 // get the maximum charstring length without actually filling up the buffer
4462 PRInt32 charStringLen;
4463 PRInt32 maxCharStringLen =
4464-#ifdef MOZ_ENABLE_XFT
4465+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4466 FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, nsnull);
4467 #else
4468 FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, nsnull);
4469 #endif
4470
4471- PRUint32 glyphID;
4472-
4473- for (i = 0; i < len; i++) {
4474-#ifdef MOZ_ENABLE_XFT
4475- glyphID = FT_Get_Char_Index(aFace, charIDs[i]);
4476+ for (i = aOffset; i < aOffset + aLen; i++) {
4477+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4478 charStringLen =
4479- FT2GlyphToType1CharString(aFace, glyphID, aWmode, aLenIV, nsnull);
4480+ FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, aLenIV,
4481+ nsnull);
4482 #else
4483- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID);
4484 charStringLen =
4485- FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, aLenIV, nsnull);
4486+ FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), aWmode, aLenIV,
4487+ nsnull);
4488 #endif
4489
4490 if (charStringLen > maxCharStringLen)
4491@@ -666,7 +784,7 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
4492 len + 1).get());
4493
4494 // output the notdef glyph
4495-#ifdef MOZ_ENABLE_XFT
4496+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4497 charStringLen = FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV,
4498 charString.get());
4499 #else
4500@@ -676,22 +794,20 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
4501
4502 // enclose charString with "/.notdef RD ..... ND"
4503 charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()),
4504- charStringLen, 0);
4505+ charStringLen, "/.notdef");
4506
4507
4508 // output the charstrings for each glyph in this sub font
4509- for (i = 0; i < len; i++) {
4510-#ifdef MOZ_ENABLE_XFT
4511- glyphID = FT_Get_Char_Index(aFace, charIDs[i]);
4512- charStringLen = FT2GlyphToType1CharString(aFace, glyphID, aWmode,
4513+ for (i = aOffset; i < aOffset + aLen; i++) {
4514+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4515+ charStringLen = FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode,
4516 aLenIV, charString.get());
4517 #else
4518- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID);
4519- charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode,
4520- aLenIV, charString.get());
4521+ charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i),
4522+ aWmode, aLenIV, charString.get());
4523 #endif
4524 charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()),
4525- charStringLen, charIDs[i]);
4526+ charStringLen, glyphnames.CStringAt(i - aOffset)->get());
4527 }
4528
4529 // wrap up the encrypted part of the font definition
4530@@ -753,15 +869,12 @@ void encryptAndHexOut(FILE *aFile, PRUin
4531
4532 /* static */
4533 void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey,
4534- const char *aStr, PRUint32 aLen, PRUnichar aId)
4535+ const char *aStr, PRUint32 aLen, const char *aGlyphName)
4536 {
4537 // use a local buffer instead of nsPrintfCString to avoid alloc.
4538 char buf[30];
4539 int oLen;
4540- if (aId == 0)
4541- oLen = PR_snprintf(buf, 30, "/.notdef %d RD ", aLen);
4542- else
4543- oLen = PR_snprintf(buf, 30, "/uni%04X %d RD ", aId, aLen);
4544+ oLen = PR_snprintf(buf, 30, "%s %d RD ", aGlyphName, aLen);
4545
4546 if (oLen >= 30) {
4547 NS_WARNING("buffer size exceeded. charstring will be truncated");
4548Index: gfx/src/ps/nsType1.h
4549===================================================================
4550RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.h,v
4551retrieving revision 1.5
4552diff -u -p -d -r1.5 nsType1.h
4553--- gfx/src/ps/nsType1.h 4 Mar 2005 07:39:27 -0000 1.5
4554+++ gfx/src/ps/nsType1.h 23 Oct 2006 17:37:39 -0000
4555@@ -122,8 +122,9 @@ FT_Error FT2GlyphToType1CharString(nsIFr
4556
4557 class nsString;
4558 class nsCString;
4559+class nsValueArray;
4560
4561-PRBool FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset,
4562+PRBool FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset,
4563 int aWmode, FILE *aFile);
4564 nsresult FT2ToType1FontName(FT_Face aFace, int aWmode,
4565 nsCString& aFontName);
4566Index: config/system-headers
4567===================================================================
4568--- config/system-headers 2006-10-26 12:21:39.000000000 -0400
4569+++ config/system-headers 2006-10-26 12:23:29.000000000 -0400
4570@@ -199,6 +199,7 @@
4571 freetype/ftoutln.h
4572 freetype/ttnameid.h
4573 freetype/tttables.h
4574+freetype/t1tables.h
4575 fribidi/fribidi.h
4576 FSp_fopen.h
4577 fstream.h
4578@@ -501,6 +503,7 @@
4579 pango/pangofc-fontmap.h
4580 pango/pango-fontmap.h
4581 pango/pango.h
4582+pango/pangoft2.h
4583 pango/pangoxft.h
4584 pango/pangox.h
4585 pango-types.h
4586
This page took 0.719677 seconds and 4 git commands to generate.