1 Patch for Firefox 1.5.0.7 to add support for printing via Pango.
2 This also implements printing MathML via Pango, and prints bitmap
10 Index: gfx/src/freetype/nsFreeType.cpp
11 ===================================================================
12 RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.cpp,v
13 retrieving revision 1.28
14 diff -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 [] = {
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},
26 @@ -388,6 +390,22 @@ nsFreeType2::GetNextChar(FT_Face face, F
30 +nsFreeType2::HasPSGlyphNames(FT_Face face, FT_Int *result)
32 + // call the FreeType2 function via the function pointer
33 + *result = nsFT_Has_PS_Glyph_Names(face);
38 +nsFreeType2::GetGlyphName(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max)
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;
46 nsFreeType2::SupportsExtFunc(PRBool *res)
49 Index: gfx/src/freetype/nsFreeType.h
50 ===================================================================
51 RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.h,v
52 retrieving revision 1.18
53 diff -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
58 #include FT_CACHE_IMAGE_H
59 #include FT_TRUETYPE_TABLES_H
60 +#include FT_TYPE1_TABLES_H
61 #include "nsIFreeType2.h"
63 typedef struct FT_FaceRec_* FT_Face;
64 @@ -138,6 +139,8 @@ typedef FT_Error (*FT_Glyph_To_Bitmap_t)
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);
73 @@ -193,11 +196,13 @@ protected:
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;
80 // this array needs to be big enough to hold all the function pointers
81 // plus one extra for the null at the end
83 - static FtFuncList FtFuncs[24];
84 + static FtFuncList FtFuncs[28];
86 // static FtFuncList FtFuncs[20];
88 Index: gfx/src/ps/Makefile.in
89 ===================================================================
90 RCS file: /cvsroot/mozilla/gfx/src/ps/Makefile.in,v
91 retrieving revision 1.57.8.1
92 diff -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) \
99 +ifdef MOZ_ENABLE_PANGO
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)
109 EXTRA_DSO_LDOPTS += \
111 @@ -105,7 +114,7 @@ EXTRA_DSO_LDOPTS += \
115 -ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT))
116 +ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)$(MOZ_ENABLE_PANGO))
120 Index: gfx/src/ps/mozilla-ps-decoder.cpp
121 ===================================================================
122 RCS file: gfx/src/ps/mozilla-ps-decoder.cpp
123 diff -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
127 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
128 +/* vim:expandtab:shiftwidth=4:tabstop=4:
130 +/* ***** BEGIN LICENSE BLOCK *****
131 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
143 + * The Original Code is mozilla.org code.
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.
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.
163 + * ***** END LICENSE BLOCK ***** */
165 +#define PANGO_ENABLE_BACKEND
166 +#define PANGO_ENABLE_ENGINE
168 +#include "mozilla-ps-decoder.h"
169 +#include <pango/pangofc-fontmap.h>
170 +#include <pango/pangofc-font.h>
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"
180 +#undef DEBUG_CUSTOM_ENCODER
182 +G_DEFINE_TYPE (MozillaPSDecoder, mozilla_ps_decoder, PANGO_TYPE_FC_DECODER)
184 +MozillaPSDecoder *mozilla_ps_decoder_new (void);
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,
192 +static PangoFcDecoder *mozilla_find_ps_decoder (FcPattern *pattern,
193 + gpointer user_data);
195 +typedef struct _MozillaPSDecoderPrivate MozillaPSDecoderPrivate;
197 +#define MOZILLA_PS_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderPrivate))
199 +struct _MozillaPSDecoderPrivate {
204 + FcCharSet *charset;
205 + nsCOMPtr<nsIUnicodeEncoder> uEncoder;
208 +static nsICharsetConverterManager *gCharsetManager = NULL;
210 +static NS_DEFINE_CID(kCharsetConverterManagerCID,
211 + NS_ICHARSETCONVERTERMANAGER_CID);
213 +// Hash tables that hold the custom encodings and custom cmaps used in
215 +static GHashTable *encoder_hash = NULL;
216 +static GHashTable *cmap_hash = NULL;
217 +static GHashTable *wide_hash = NULL;
220 +mozilla_ps_decoder_init (MozillaPSDecoder *decoder)
225 +mozilla_ps_decoder_class_init (MozillaPSDecoderClass *klass)
227 + GObjectClass *object_class = G_OBJECT_CLASS(klass);
228 + PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
230 + /* object_class->finalize = test_finalize; */
232 + parent_class->get_charset = mozilla_ps_decoder_get_charset;
233 + parent_class->get_glyph = mozilla_ps_decoder_get_glyph;
235 + g_type_class_add_private (object_class, sizeof (MozillaPSDecoderPrivate));
239 +mozilla_ps_decoder_new(void)
241 + return (MozillaPSDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
244 +#ifdef DEBUG_CUSTOM_ENCODER
246 +dump_hash(char *key, char *val, void *arg)
248 + printf("%s -> %s\n", key, val);
253 + * mozilla_ps_decoders_init:
255 + * #mozilla_ps_decoders_init:
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.
261 + * Return value: zero on success, not zero on failure.
266 +mozilla_ps_decoders_init(PangoFontMap *fontmap)
268 + static PRBool initialized = PR_FALSE;
272 + if (!PANGO_IS_FC_FONT_MAP (fontmap))
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);
279 + PRBool dumb = PR_FALSE;
280 + nsCOMPtr<nsIPersistentProperties> props;
281 + nsCOMPtr<nsISimpleEnumerator> encodeEnum;
283 + NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
284 + NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
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));
295 + while (encodeEnum->HasMoreElements(&dumb), dumb) {
296 + nsCOMPtr<nsIPropertyElement> prop;
297 + encodeEnum->GetNext(getter_AddRefs(prop));
301 + nsCAutoString name;
302 + prop->GetKey(name);
303 + nsAutoString value;
304 + prop->GetValue(value);
306 + if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
307 + printf("string doesn't begin with encoding?\n");
311 + name = Substring(name, 9);
313 + if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
314 + name = Substring(name, 0, name.Length() - 4);
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()),
320 + value = Substring(value, 0, name.Length() - 5);
323 + g_hash_table_insert(encoder_hash,
324 + g_strdup(name.get()),
325 + g_strdup(NS_ConvertUTF16toUTF8(value).get()));
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()));
334 + printf("unknown suffix used for mapping\n");
338 + pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(fontmap),
339 + mozilla_find_ps_decoder,
343 + initialized = PR_TRUE;
345 +#ifdef DEBUG_CUSTOM_ENCODER
346 + printf("*** encoders\n");
347 + g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
349 + printf("*** cmaps\n");
350 + g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
360 +mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder,
361 + PangoFcFont *fcfont)
363 + MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
366 + return priv->charset;
368 + // First time this has been accessed. Populate the charset.
369 + priv->charset = FcCharSetCreate();
371 + if (!gCharsetManager) {
372 + CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
375 + nsCOMPtr<nsIUnicodeEncoder> encoder;
376 + nsCOMPtr<nsICharRepresentable> represent;
378 + if (!gCharsetManager)
381 + gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
385 + encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
387 + priv->uEncoder = encoder;
389 + represent = do_QueryInterface(encoder);
393 + PRUint32 map[UCS2_MAP_LEN];
394 + memset(map, 0, sizeof(map));
396 + represent->FillInfo(map);
398 + for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
399 + if (IS_REPRESENTABLE(map, i))
400 + FcCharSetAddChar(priv->charset, i);
404 + return priv->charset;
408 +mozilla_ps_decoder_get_glyph (PangoFcDecoder *decoder,
409 + PangoFcFont *fcfont,
412 + MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
414 + PangoGlyph retval = 0;
415 + PRUnichar inchar = wc;
417 + char outchar[2] = {0,0};
418 + PRInt32 outlen = 2;
420 + priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
422 + printf("Warning: mozilla_ps_decoder_get_glyph doesn't support more than one character conversions.\n");
426 + FT_Face face = pango_fc_font_lock_face(fcfont);
428 +#ifdef DEBUG_CUSTOM_ENCODER
430 + FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
431 + printf("filename is %s\n", filename);
434 + // Make sure to set the right charmap before trying to get the
437 + if (!strcmp(priv->cmap, "mac_roman")) {
438 + FT_Select_Charmap(face, ft_encoding_apple_roman);
440 + else if (!strcmp(priv->cmap, "unicode")) {
441 + FT_Select_Charmap(face, ft_encoding_unicode);
444 + printf("Warning: Invalid charmap entry for family %s\n",
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);
459 + printf("Warning: We don't support .wide fonts!\n");
463 + pango_fc_font_unlock_face(fcfont);
468 +static PangoFcDecoder *
469 +mozilla_find_ps_decoder (FcPattern *pattern, gpointer user_data)
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);
476 + nsCAutoString family;
477 + family.Assign(orig);
479 + family.StripWhitespace();
480 + ToLowerCase(family);
482 + char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
486 + MozillaPSDecoder *decoder = mozilla_ps_decoder_new();
488 + MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
490 + priv->family = g_strdup(family.get());
491 + priv->encoder = g_strdup(encoder);
493 + char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
495 + priv->cmap = g_strdup(cmap);
497 + char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
499 + priv->is_wide = TRUE;
501 + return PANGO_FC_DECODER(decoder);
503 Index: gfx/src/ps/mozilla-ps-decoder.h
504 ===================================================================
505 RCS file: gfx/src/ps/mozilla-ps-decoder.h
506 diff -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
510 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
511 +/* vim:expandtab:shiftwidth=4:tabstop=4:
513 +/* ***** BEGIN LICENSE BLOCK *****
514 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
526 + * The Original Code is mozilla.org code.
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.
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.
546 + * ***** END LICENSE BLOCK ***** */
548 +#ifndef _MOZILLA_PS_DECODER_H
549 +#define _MOZILLA_PS_DECODER_H
551 +#include <pango/pangofc-decoder.h>
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))
559 +typedef struct _MozillaPSDecoder MozillaPSDecoder;
560 +typedef struct _MozillaPSDecoderClass MozillaPSDecoderClass;
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))
566 +struct _MozillaPSDecoder
568 + PangoFcDecoder parent_instance;
571 +struct _MozillaPSDecoderClass
573 + PangoFcDecoderClass parent_class;
576 +GType mozilla_ps_decoder_get_type (void);
577 +int mozilla_ps_decoders_init (PangoFontMap *fontmap);
581 +#endif /*_MOZILLA_PS_DECODER_H */
582 Index: gfx/src/ps/nsDeviceContextPS.cpp
583 ===================================================================
584 RCS file: /cvsroot/mozilla/gfx/src/ps/nsDeviceContextPS.cpp,v
585 retrieving revision 1.73
586 diff -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
591 #include "nsString.h"
592 #include "nsFontMetricsPS.h"
593 +#ifdef MOZ_ENABLE_PANGO
594 +#include "nsFontMetricsPSPango.h"
596 #include "nsPostScriptObj.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)
606 @@ -223,7 +226,7 @@ nsDeviceContextPS::InitDeviceContextPS(n
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);
615 @@ -469,7 +472,7 @@ NS_IMETHODIMP nsDeviceContextPS::EndDocu
616 NS_ASSERTION(submitFP, "No print job submission handle");
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);
623 mPSObj->write_prolog(submitFP);
624 @@ -550,15 +553,52 @@ public:
625 virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** aResult);
628 +#if defined(MOZ_ENABLE_PANGO)
630 +NS_IsPangoEnabled(void)
632 + static PRBool beenHere;
633 + static PRBool pangoEnabled;
636 + beenHere = PR_TRUE;
638 + char *val = PR_GetEnv("MOZ_DISABLE_PANGO");
639 + pangoEnabled = !(val);
641 + if (pangoEnabled) {
642 + nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID);
644 + prefService->SetDefaultCharPref("general.useragent.extra.pango",
649 + return pangoEnabled;
653 nsresult nsFontCachePS::CreateFontMetricsInstance(nsIFontMetrics** aResult)
655 NS_PRECONDITION(aResult, "null out param");
656 - nsIFontMetrics *fm = new nsFontMetricsPS();
658 - return NS_ERROR_OUT_OF_MEMORY;
661 +#ifdef MOZ_ENABLE_PANGO
662 + if (NS_IsPangoEnabled())
664 + nsIFontMetrics *fm = new nsFontMetricsPSPango();
666 + return NS_ERROR_OUT_OF_MEMORY;
673 + nsIFontMetrics *fm = new nsFontMetricsPS();
675 + return NS_ERROR_OUT_OF_MEMORY;
682 Index: gfx/src/ps/nsFontMetricsPS.cpp
683 ===================================================================
684 RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.cpp,v
685 retrieving revision 1.57.16.2
686 diff -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
694 +nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
695 + nscoord aX, nscoord aY,
696 + const nscoord* aSpacing,
697 + nsRenderingContextPS *aContext)
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) {
704 + nsCOMPtr<nsIAtom> langGroup;
705 + GetLangGroup(getter_AddRefs(langGroup));
706 + psObj->setlanggroup(langGroup);
707 +#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
713 + nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
714 + NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
715 + fontPS->SetupFont(aContext);
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);
728 + // setup for following text
729 + fontPS = fontThisChar;
730 + fontPS->SetupFont(aContext);
734 + // draw the last part
736 + DrawString(aString+start, aLength-start, aX, aY, fontPS,
737 + aSpacing?aSpacing+start:nsnull, aContext);
743 +nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
744 + nscoord aX, nscoord aY,
746 + const nscoord* aSpacing,
747 + nsRenderingContextPS *aContext)
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) {
754 + nsCOMPtr<nsIAtom> langGroup = nsnull;
755 + GetLangGroup(getter_AddRefs(langGroup));
756 + psObj->setlanggroup(langGroup);
757 +#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
761 + /* build up conversion table */
762 + psObj->preshow(aString, aLength);
766 + nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
767 + NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
768 + fontPS->SetupFont(aContext);
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);
781 + // setup for following text
782 + fontPS = fontThisChar;
783 + fontPS->SetupFont(aContext);
787 + // draw the last part
789 + DrawString(aString+start, aLength-start, aX, aY, fontPS,
790 + aSpacing?aSpacing+start:nsnull, aContext);
796 +nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
797 + nscoord aX, nscoord aY, nsFontPS* aFontPS,
798 + const nscoord* aSpacing,
799 + nsRenderingContextPS *aContext)
805 + PRInt32 dxMem[500];
809 + if (aLength > 500) {
810 + dx0 = new PRInt32[aLength];
811 + NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
813 + aContext->GetTranMatrix()->ScaleXCoords(aSpacing, aLength, dx0);
816 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
817 + width = aFontPS->DrawString(aContext, x, y, aString, aLength);
819 + if ((aSpacing) && (dx0 != dxMem)) {
828 +nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
829 + nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
830 + const nscoord* aSpacing,
831 + nsRenderingContextPS *aContext)
838 + // Slow, but accurate rendering
839 + const PRUnichar* end = aString + aLength;
840 + while (aString < end){
843 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
844 + aFontPS->DrawString(aContext, x, y, aString, 1);
850 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
851 + width = aFontPS->DrawString(aContext, x, y, aString, aLength);
858 +nsFontMetricsPS::GetTextDimensions(const char* aString,
860 + PRInt32 aAvailWidth,
862 + PRInt32 aNumBreaks,
863 + nsTextDimensions& aDimensions,
864 + PRInt32& aNumCharsFit,
865 + nsTextDimensions& aLastWordDimensions,
868 + NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
869 + return NS_ERROR_NOT_IMPLEMENTED;
873 +nsFontMetricsPS::GetTextDimensions(const PRUnichar* aString,
875 + PRInt32 aAvailWidth,
877 + PRInt32 aNumBreaks,
878 + nsTextDimensions& aDimensions,
879 + PRInt32& aNumCharsFit,
880 + nsTextDimensions& aLastWordDimensions,
883 + NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
884 + return NS_ERROR_NOT_IMPLEMENTED;
888 +nsFontMetricsPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
889 + nsTextDimensions& aDimensions)
891 + GetStringWidth(aString, aDimensions.width, aLength);
892 + GetMaxAscent(aDimensions.ascent);
893 + GetMaxDescent(aDimensions.descent);
898 +nsFontMetricsPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
899 + nsTextDimensions& aDimensions, PRInt32* aFontID)
901 + GetStringWidth(aString, aDimensions.width, aLength);
902 + //XXX temporary - bug 96609
903 + GetMaxAscent(aDimensions.ascent);
904 + GetMaxDescent(aDimensions.descent);
909 +nsFontMetricsPS::GetBoundingMetrics(const char* aString,
911 + nsBoundingMetrics& aBoundingMetrics)
913 + return NS_ERROR_NOT_IMPLEMENTED;
917 +nsFontMetricsPS::GetBoundingMetrics(const PRUnichar* aString,
919 + nsBoundingMetrics &aBoundingMetrics,
922 + return NS_ERROR_NOT_IMPLEMENTED;
927 nsFontPS::FindFont(char aChar, const nsFont& aFont,
928 nsFontMetricsPS* aFontMetrics)
929 @@ -1128,23 +1361,38 @@ nsFontPSXft::DrawString(nsRenderingConte
933 + FT_Face face = getFTFace();
935 + NS_WARNING("Failed to get FT Face in nsFontPSXft::DrawString\n");
939 + nsValueArray glyphs(PR_UINT16_MAX);
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);
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);
955 NS_ASSERTION(!mFontNameBase.IsEmpty(),
956 "font base name shouldn't be empty");
957 psObj->setfont(mFontNameBase, mHeight, currSubFont);
958 prevSubFont = currSubFont;
963 + glyphs.AppendValue(glyph);
966 - if (prevSubFont != -1)
967 - psObj->show(&aString[start], i - start, *subSet, prevSubFont);
968 + if (prevSubFont != -1) {
969 + psObj->show(&glyphs, mPSFontGenerator, prevSubFont);
972 return GetWidth(aString, aLength);
974 @@ -2278,10 +2526,13 @@ nsFontPSFreeType::GetBoundingMetrics(con
975 // Implementation of nsPSFontGenerator
976 nsPSFontGenerator::nsPSFontGenerator()
978 + mGlyphSubset = new nsValueArray(PR_UINT16_MAX, 40);
981 nsPSFontGenerator::~nsPSFontGenerator()
984 + delete mGlyphSubset;
987 void nsPSFontGenerator::GeneratePSFont(FILE* aFile)
988 @@ -2289,24 +2540,29 @@ void nsPSFontGenerator::GeneratePSFont(F
989 NS_ERROR("should never call nsPSFontGenerator::GeneratePSFont");
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.
1001 -nsPSFontGenerator::AddToSubset(PRUnichar aChar)
1002 +nsPSFontGenerator::AddToGlyphSubset(PRUint32 aGlyph)
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;
1014 return index / kSubFontSize;
1017 -nsString *nsPSFontGenerator::GetSubset()
1019 +nsPSFontGenerator::InSubsetIndexOf(PRUint32 aGlyph)
1022 + nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph);
1023 + if (index == NSVALUEARRAY_INVALID)
1025 + return (index % kSubFontSize) + 1;
1028 #ifdef MOZ_ENABLE_XFT
1029 @@ -2353,8 +2609,8 @@ void nsXftType1Generator::GeneratePSFont
1033 - if (!mSubset.IsEmpty())
1034 - FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
1035 + if (mGlyphSubset->Count())
1036 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
1040 @@ -2402,8 +2658,8 @@ void nsFT2Type1Generator::GeneratePSFont
1044 - if (!mSubset.IsEmpty())
1045 - FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
1046 + if (mGlyphSubset->Count())
1047 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
1050 #endif //MOZ_ENABLE_FREETYPE2
1051 Index: gfx/src/ps/nsFontMetricsPS.h
1052 ===================================================================
1053 RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.h,v
1054 retrieving revision 1.31
1055 diff -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
1060 #include "nsVoidArray.h"
1061 #include "nsHashtable.h"
1062 +#include "nsValueArray.h"
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);
1071 + NS_IMETHOD GetTextDimensions(const char* aString,
1073 + nsTextDimensions& aDimensions);
1074 + NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
1076 + nsTextDimensions& aDimensions,
1077 + PRInt32* aFontID);
1078 + NS_IMETHOD GetTextDimensions(const char* aString,
1080 + PRInt32 aAvailWidth,
1082 + PRInt32 aNumBreaks,
1083 + nsTextDimensions& aDimensions,
1084 + PRInt32& aNumCharsFit,
1085 + nsTextDimensions& aLastWordDimensions,
1086 + PRInt32* aFontID);
1087 + NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
1089 + PRInt32 aAvailWidth,
1091 + PRInt32 aNumBreaks,
1092 + nsTextDimensions& aDimensions,
1093 + PRInt32& aNumCharsFit,
1094 + nsTextDimensions& aLastWordDimensions,
1095 + PRInt32* aFontID);
1097 + NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
1098 + nsBoundingMetrics &aBoundingMetrics);
1099 + NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString,
1101 + nsBoundingMetrics &aBoundingMetrics,
1102 + PRInt32 *aFontID);
1103 +#endif /* MOZ_MATHML */
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,
1112 + const nscoord* aSpacing,
1113 + nsRenderingContextPS *aContext);
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);
1127 + virtual PRUint32 GetHints (void) { return 0; }
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);
1141 // 256 (PS type 1 encoding vector size) - 1 (1 is for mandatory /.notdef)
1142 const static PRUint16 kSubFontSize;
1145 - // XXX To support non-BMP characters, we may have to use
1146 - // nsValueArray with PRUint32
1148 + nsValueArray *mGlyphSubset;
1152 Index: gfx/src/ps/nsFontMetricsPSPango.cpp
1153 ===================================================================
1154 RCS file: gfx/src/ps/nsFontMetricsPSPango.cpp
1155 diff -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
1159 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
1160 +/* vim:expandtab:shiftwidth=4:tabstop=4:
1162 +/* ***** BEGIN LICENSE BLOCK *****
1163 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
1175 + * The Original Code is mozilla.org code.
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.
1182 + * Christopher Blizzard <blizzard@mozilla.org>
1183 + * Behdad Esfahbod <behdad@behdad.org>
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.
1197 + * ***** END LICENSE BLOCK ***** */
1199 +#include <strings.h>
1200 +#include "nsFont.h"
1201 +#include "nsIDeviceContext.h"
1202 +#include "nsICharsetConverterManager.h"
1203 +#include "nsIPref.h"
1204 +#include "nsServiceManagerUtils.h"
1206 +#define PANGO_ENABLE_BACKEND
1207 +#define PANGO_ENABLE_ENGINE
1209 +#include "nsFontMetricsPSPango.h"
1210 +#include "nsRenderingContextPS.h"
1211 +#include "nsDeviceContextPS.h"
1212 +#include "nsFontConfigUtils.h"
1214 +#include "nsPrintfCString.h"
1215 +#include "nsUnicharUtils.h"
1216 +#include "nsQuickSort.h"
1217 +#include "nsFontConfigUtils.h"
1219 +#include <fontconfig/fontconfig.h>
1220 +#include <pango/pangoft2.h>
1221 +#include <freetype/tttables.h>
1222 +#include "nsType1.h"
1224 +#include "mozilla-ps-decoder.h"
1226 +#define FORCE_PR_LOG
1231 +static PRLogModuleInfo *gPangoFontLog;
1232 +static int gNumInstances;
1236 +default_substitute (FcPattern *pattern,
1239 + FcPatternDel (pattern, FC_HINTING);
1240 + FcPatternAddBool (pattern, FC_HINTING, 0);
1243 +static PangoFontMap *
1246 + static PangoFontMap *fontmap = NULL;
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);
1257 +static PangoContext *
1260 + return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
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
1271 +static NS_DEFINE_CID(kCharsetConverterManagerCID,
1272 + NS_ICHARSETCONVERTERMANAGER_CID);
1275 +#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \
1276 + printf("0x%x ", ustr[llen]); \
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))))
1288 +// Static function decls
1290 +static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup);
1292 +static void FreeGlobals (void);
1294 +static PangoStyle CalculateStyle (PRUint8 aStyle);
1295 +static PangoWeight CalculateWeight (PRUint16 aWeight);
1297 +static nsresult EnumFontsPango (nsIAtom* aLangGroup, const char* aGeneric,
1298 + PRUint32* aCount, PRUnichar*** aResult);
1299 +static int CompareFontNames (const void* aArg1, const void* aArg2,
1302 +nsFontMetricsPSPango::nsFontMetricsPSPango()
1304 + if (!gPangoFontLog)
1305 + gPangoFontLog = PR_NewLogModule("PangoFont");
1309 + mPangoFontDesc = nsnull;
1310 + mPangoContext = nsnull;
1311 + mLTRPangoContext = nsnull;
1312 + mRTLPangoContext = nsnull;
1313 + mPangoAttrList = nsnull;
1314 + mIsRTL = PR_FALSE;
1315 + mPangoSpaceWidth = 0;
1317 + static PRBool initialized = PR_FALSE;
1321 + // Initialized the custom decoders
1322 + if (!mozilla_ps_decoders_init(get_fontmap ()))
1323 + initialized = PR_TRUE;
1326 +nsFontMetricsPSPango::~nsFontMetricsPSPango()
1328 + if (mDeviceContext)
1329 + mDeviceContext->FontMetricsDeleted(this);
1331 + if (mPangoFontDesc)
1332 + pango_font_description_free(mPangoFontDesc);
1334 + if (mLTRPangoContext)
1335 + g_object_unref(mLTRPangoContext);
1337 + if (mRTLPangoContext)
1338 + g_object_unref(mRTLPangoContext);
1340 + if (mPangoAttrList)
1341 + pango_attr_list_unref(mPangoAttrList);
1343 + // XXX clean up all the pango objects
1345 + if (--gNumInstances == 0)
1350 +NS_IMPL_ISUPPORTS1(nsFontMetricsPSPango, nsIFontMetrics)
1352 +// nsIFontMetrics impl
1355 +nsFontMetricsPSPango::Init(const nsFont& aFont, nsIAtom* aLangGroup,
1356 + nsIDeviceContext *aContext)
1359 + mLangGroup = aLangGroup;
1361 + // Hang on to the device context
1362 + mDeviceContext = aContext;
1364 + mPointSize = NSTwipsToFloatPoints(mFont.size);
1366 + // enumerate over the font names passed in
1367 + mFont.EnumerateFamilies(nsFontMetricsPSPango::EnumFontCallback, this);
1369 + nsCOMPtr<nsIPref> prefService;
1370 + prefService = do_GetService(NS_PREF_CONTRACTID);
1372 + return NS_ERROR_FAILURE;
1374 + nsXPIDLCString value;
1375 + const char* langGroup;
1376 + mLangGroup->GetUTF8String(&langGroup);
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));
1385 + mDefaultFont = value.get();
1387 + mDefaultFont = "serif";
1389 + mGenericFont = &mDefaultFont;
1392 + // set up the minimum sizes for fonts
1394 + nsCAutoString name("font.min-size.");
1396 + if (mGenericFont->Equals("monospace"))
1397 + name.Append("fixed");
1399 + name.Append("variable");
1401 + name.Append(char('.'));
1402 + name.Append(langGroup);
1404 + PRInt32 minimumInt = 0;
1407 + res = prefService->GetIntPref(name.get(), &minimumInt);
1408 + if (NS_FAILED(res))
1409 + prefService->GetDefaultIntPref(name.get(), &minimumInt);
1411 + if (minimumInt < 0)
1414 + minimum = minimumInt;
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;
1423 + // Make sure that the pixel size is at least greater than zero
1424 + if (mPointSize < 1) {
1426 + printf("*** Warning: nsFontMetricsPSPango created with point size %f\n",
1432 + nsresult rv = RealizeFont();
1433 + if (NS_FAILED(rv))
1436 + // Cache font metrics for the 'x' character
1437 + return CacheFontMetrics();
1441 +nsFontMetricsPSPango::CacheFontMetrics(void)
1443 + // Get our scale factor
1446 + f = mDeviceContext->DevUnitsToAppUnits();
1448 + mPangoAttrList = pango_attr_list_new();
1450 + GList *items = pango_itemize(mPangoContext,
1451 + "a", 0, 1, mPangoAttrList, NULL);
1454 + return NS_ERROR_FAILURE;
1456 + guint nitems = g_list_length(items);
1458 + return NS_ERROR_FAILURE;
1460 + PangoItem *item = (PangoItem *)items->data;
1461 + PangoFcFont *fcfont = PANGO_FC_FONT(item->analysis.font);
1463 + return NS_ERROR_FAILURE;
1465 + // Get our font face
1467 + face = pango_fc_font_lock_face(fcfont);
1469 + return NS_ERROR_NOT_AVAILABLE;
1472 + os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1474 + // mEmHeight (size in pixels of EM height)
1476 + if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) !=
1480 + mEmHeight = PR_MAX(1, nscoord(size * f));
1483 + val = MOZ_FT_TRUNC(face->size->metrics.ascender);
1484 + mMaxAscent = NSToIntRound(val * f);
1487 + val = -MOZ_FT_TRUNC(face->size->metrics.descender);
1488 + mMaxDescent = NSToIntRound(val * f);
1490 + nscoord lineHeight = mMaxAscent + mMaxDescent;
1492 + // mLeading (needs ascent and descent and EM height)
1493 + if (lineHeight > mEmHeight)
1494 + mLeading = lineHeight - mEmHeight;
1498 + // mMaxHeight (needs ascent and descent)
1499 + mMaxHeight = lineHeight;
1501 + // mEmAscent (needs maxascent, EM height, ascent and descent)
1502 + mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight);
1504 + // mEmDescent (needs EM height and EM ascent
1505 + mEmDescent = mEmHeight - mEmAscent;
1508 + val = MOZ_FT_TRUNC(face->size->metrics.max_advance);
1509 + mMaxAdvance = NSToIntRound(val * f);
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);
1519 + // mSpaceWidth (width of a space)
1521 + GetWidth(" ", 1, tmpWidth);
1522 + mSpaceWidth = tmpWidth;
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;
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);
1539 + // 56% of ascent, best guess for non-true type or asian fonts
1540 + mXHeight = nscoord(((float)mMaxAscent) * 0.56 * f);
1543 + // mUnderlineOffset (offset for underlines)
1544 + val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position,
1545 + face->size->metrics.y_scale);
1547 + mUnderlineOffset = NSToIntRound(val * f);
1550 + mUnderlineOffset =
1551 + -NSToIntRound(PR_MAX(1, floor(0.1 *
1552 + MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
1555 + // mUnderlineSize (thickness of an underline)
1556 + val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness,
1557 + face->size->metrics.y_scale);
1559 + mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1563 + NSToIntRound(PR_MAX(1,
1564 + floor(0.05 * MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
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)));
1574 + mSuperscriptOffset = mXHeight;
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)));
1586 + mSubscriptOffset = mXHeight;
1589 + // mStrikeoutOffset
1590 + mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
1593 + mStrikeoutSize = mUnderlineSize;
1595 + pango_fc_font_unlock_face(fcfont);
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);
1621 +nsFontMetricsPSPango::Destroy()
1623 + mDeviceContext = nsnull;
1628 +nsFontMetricsPSPango::GetLangGroup(nsIAtom** aLangGroup)
1630 + *aLangGroup = mLangGroup;
1631 + NS_IF_ADDREF(*aLangGroup);
1637 +nsFontMetricsPSPango::GetFontHandle(nsFontHandle &aHandle)
1639 + return NS_ERROR_NOT_IMPLEMENTED;
1642 +// nsIFontMetricsPango impl
1644 +nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
1646 + return GetWidth (String, (PRUint32) aLength, aWidth);
1650 +nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
1652 + return GetWidth (aString, (PRUint32)aLength, aWidth);
1656 +nsFontMetricsPSPango::GetWidth(const char* aString, PRUint32 aLength,
1659 + PangoLayout *layout = pango_layout_new(mPangoContext);
1661 + pango_layout_set_text(layout, aString, aLength);
1663 + if (mPangoSpaceWidth)
1664 + FixupSpaceWidths(layout, aString);
1666 + int width, height;
1668 + pango_layout_get_size(layout, &width, &height);
1670 + g_object_unref(layout);
1673 + f = mDeviceContext->DevUnitsToAppUnits();
1674 + aWidth = NSToCoordRound(width * f / PANGO_SCALE);
1676 + // printf("GetWidth (char *) %d\n", aWidth);
1682 +nsFontMetricsPSPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
1685 + nsresult rv = NS_OK;
1686 + PangoLayout *layout = pango_layout_new(mPangoContext);
1688 + gchar *text = g_utf16_to_utf8(aString, aLength,
1689 + NULL, NULL, NULL);
1694 + NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
1695 + DUMP_PRUNICHAR(aString, aLength)
1697 + rv = NS_ERROR_FAILURE;
1701 + gint width, height;
1703 + pango_layout_set_text(layout, text, strlen(text));
1704 + FixupSpaceWidths(layout, text);
1705 + pango_layout_get_size(layout, &width, &height);
1708 + f = mDeviceContext->DevUnitsToAppUnits();
1709 + aWidth = NSToCoordRound(width * f / PANGO_SCALE);
1711 + // printf("GetWidth %d\n", aWidth);
1715 + g_object_unref(layout);
1722 +nsFontMetricsPSPango :: GetTextDimensions(const char* aString, PRUint32 aLength,
1723 + nsTextDimensions& aDimensions)
1725 + nsresult rv = NS_OK;
1727 + PangoLayout *layout = pango_layout_new(mPangoContext);
1729 + pango_layout_set_text(layout, aString, aLength);
1730 + FixupSpaceWidths(layout,aString);
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");
1737 + line = pango_layout_get_line(layout, 0);
1739 + PangoRectangle rect;
1740 + pango_layout_line_get_extents(line, NULL, &rect);
1743 + P2T = mDeviceContext->DevUnitsToAppUnits();
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);
1749 + // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
1750 + //aDimensions.ascent, aDimensions.descent);
1753 + g_object_unref(layout);
1759 +nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString,
1761 + nsTextDimensions& aDimensions,
1764 + nsresult rv = NS_OK;
1766 + PangoLayout *layout = pango_layout_new(mPangoContext);
1768 + gchar *text = g_utf16_to_utf8(aString, aLength,
1769 + NULL, NULL, NULL);
1773 + NS_WARNING("nsFontMetricsPSPango::GetTextDimensions invalid unicode to follow");
1774 + DUMP_PRUNICHAR(aString, aLength)
1776 + aDimensions.width = 0;
1777 + aDimensions.ascent = 0;
1778 + aDimensions.descent = 0;
1780 + rv = NS_ERROR_FAILURE;
1785 + pango_layout_set_text(layout, text, strlen(text));
1786 + FixupSpaceWidths(layout, text);
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");
1793 + line = pango_layout_get_line(layout, 0);
1795 + PangoRectangle rect;
1796 + pango_layout_line_get_extents(line, NULL, &rect);
1799 + P2T = mDeviceContext->DevUnitsToAppUnits();
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);
1805 + // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
1806 + //aDimensions.ascent, aDimensions.descent);
1810 + g_object_unref(layout);
1816 +nsFontMetricsPSPango::GetTextDimensions(const char* aString,
1818 + PRInt32 aAvailWidth,
1820 + PRInt32 aNumBreaks,
1821 + nsTextDimensions& aDimensions,
1822 + PRInt32& aNumCharsFit,
1823 + nsTextDimensions& aLastWordDimensions,
1827 + return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
1828 + aNumBreaks, aDimensions, aNumCharsFit,
1829 + aLastWordDimensions);
1834 +nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString,
1836 + PRInt32 aAvailWidth,
1838 + PRInt32 aNumBreaks,
1839 + nsTextDimensions& aDimensions,
1840 + PRInt32& aNumCharsFit,
1841 + nsTextDimensions& aLastWordDimensions,
1844 + nsresult rv = NS_OK;
1845 + PRInt32 curBreak = 0;
1848 + PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
1850 + gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
1851 + NULL, NULL, NULL);
1857 + NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
1858 + DUMP_PRUNICHAR(aString, (PRUint32)aLength)
1860 + rv = NS_ERROR_FAILURE;
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;
1872 + if (IS_HIGH_SURROGATE(aString[curOffset]))
1876 + // Always catch the last break
1877 + utf8Breaks[curBreak] = curChar - text;
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]);
1890 + // We'll use curBreak to indicate which of the breaks end up being
1891 + // used for the break point for this line.
1893 + rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
1894 + aNumBreaks, aDimensions, aNumCharsFit,
1895 + aLastWordDimensions);
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];
1912 + delete[] utf8Breaks;
1917 +typedef struct _nsPSPangoRenderer nsPSPangoRenderer;
1918 +typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass;
1920 +struct _nsPSPangoRenderer
1922 + PangoRenderer parent_instance;
1923 + nsRenderingContextPS *psContext;
1924 + nsFontMetricsPSPango *psPangoFontMetrics;
1928 +struct _nsPSPangoRendererClass
1930 + PangoRendererClass parent_class;
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))
1940 +G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
1942 +static PangoRenderer *
1943 +get_renderer (void)
1945 + static PangoRenderer *renderer = NULL;
1948 + renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
1954 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
1956 + PangoGlyphString *glyphs,
1961 +_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
1963 + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
1965 + renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
1969 +_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
1973 +class nsPangoType1Generator : public nsPSFontGenerator {
1975 + nsPangoType1Generator();
1976 + ~nsPangoType1Generator();
1977 + nsresult Init(PangoFont *aFont);
1978 + void GeneratePSFont(FILE* aFile);
1984 +nsPangoType1Generator::nsPangoType1Generator()
1989 +nsPangoType1Generator::Init(PangoFont *aFont)
1991 + NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
1993 + g_object_ref (mFont);
1997 +nsPangoType1Generator::~nsPangoType1Generator()
1999 + g_object_unref (mFont);
2003 +void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
2005 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
2007 + if (face == nsnull)
2011 + if (mGlyphSubset->Count())
2012 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
2014 + pango_fc_font_unlock_face ((PangoFcFont *) mFont);
2019 + nsCString *FontNameBase;
2020 + nsCStringKey *key;
2025 +ps_pango_font_data_destroy (PSPangoFontData *data)
2028 + delete data->FontNameBase;
2033 +flattenName(nsCString& aString)
2035 + nsCString::iterator start, end;
2036 + aString.BeginWriting(start);
2037 + aString.EndWriting(end);
2038 + while(start != end) {
2039 + if (*start == ' ')
2041 + else if (*start == '(')
2043 + else if (*start == ')')
2050 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
2052 + PangoGlyphString *glyphs,
2056 + if (!glyphs->num_glyphs)
2059 + static GQuark data_quark = 0;
2061 + data_quark = g_quark_from_static_string ("ps-pango-font-data");
2063 + PSPangoFontData *data;
2064 + if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
2066 + data = g_new (PSPangoFontData, 1);
2068 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
2069 + if (face == nsnull)
2072 + data->FontNameBase = new nsCString ();
2073 + if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
2075 + pango_fc_font_unlock_face ((PangoFcFont *) font);
2078 + pango_fc_font_unlock_face ((PangoFcFont *) font);
2080 + PangoFontDescription *desc = pango_font_describe (font);
2081 + data->font_size = pango_font_description_get_size (desc);
2082 + pango_font_description_free (desc);
2084 + data->key = new nsCStringKey (*data->FontNameBase);
2086 + g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
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);
2099 + psFontGen = new nsPangoType1Generator;
2100 + g_return_if_fail (psFontGen);
2101 + rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
2102 + if (NS_FAILED(rv)) {
2106 + psFGList->Put(data->key, (void *) psFontGen);
2108 + nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
2110 + g_return_if_fail (aContext);
2111 + g_return_if_fail (psObj);
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);
2117 + PRInt32 currSubFont, prevSubFont = -1;
2119 + PangoGlyphString gl;
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);
2130 + psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
2131 + prevSubFont = currSubFont;
2132 + gl.glyphs = glyphs->glyphs + i;
2133 + gl.num_glyphs = 0;
2139 + if (prevSubFont != -1)
2140 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
2144 +draw_layout_line (int x, int y, PangoLayoutLine *line, nsFontMetricsPSPango *aPSPangoFontMetrics, nsRenderingContextPS *aContext)
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();
2153 + pango_renderer_draw_layout_line (renderer, line,
2154 + NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
2155 + NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
2159 +nsFontMetricsPSPango::DrawString(const char *aString, PRUint32 aLength,
2160 + nscoord aX, nscoord aY,
2161 + const nscoord* aSpacing,
2162 + nsRenderingContextPS *aContext)
2164 + PangoLayout *layout = pango_layout_new(mPangoContext);
2166 + pango_layout_set_text(layout, aString, aLength);
2167 + FixupSpaceWidths(layout, aString);
2172 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
2174 + PangoLayoutLine *line;
2175 + if (pango_layout_get_line_count(layout) != 1) {
2176 + printf("Warning: more than one line!\n");
2178 + line = pango_layout_get_line(layout, 0);
2180 + if (aSpacing && *aSpacing) {
2181 + DrawStringSlowly(aString, NULL, aLength, x, y, line, aSpacing, aContext);
2184 + draw_layout_line (x, y, line, this, aContext);
2187 + g_object_unref(layout);
2193 +nsFontMetricsPSPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
2194 + nscoord aX, nscoord aY,
2196 + const nscoord* aSpacing,
2197 + nsRenderingContextPS *aContext)
2199 + nsresult rv = NS_OK;
2203 + PangoLayout *layout = pango_layout_new(mPangoContext);
2205 + gchar *text = g_utf16_to_utf8(aString, aLength,
2206 + NULL, NULL, NULL);
2209 + NS_WARNING("nsFontMetricsPSPango::DrawString invalid unicode to follow");
2210 + DUMP_PRUNICHAR(aString, aLength)
2212 + rv = NS_ERROR_FAILURE;
2216 + pango_layout_set_text(layout, text, strlen(text));
2217 + FixupSpaceWidths(layout, text);
2219 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
2221 + PangoLayoutLine *line;
2222 + if (pango_layout_get_line_count(layout) != 1) {
2223 + printf("Warning: more than one line!\n");
2225 + line = pango_layout_get_line(layout, 0);
2227 + if (aSpacing && *aSpacing) {
2228 + DrawStringSlowly(text, aString, aLength, x, y, line, aSpacing, aContext);
2231 + draw_layout_line (x, y, line, this, aContext);
2237 + g_object_unref(layout);
2244 +nsFontMetricsPSPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
2245 + nsBoundingMetrics &aBoundingMetrics)
2247 + printf("GetBoundingMetrics (char *)\n");
2248 + return NS_ERROR_FAILURE;
2252 +nsFontMetricsPSPango::GetBoundingMetrics(const PRUnichar *aString,
2254 + nsBoundingMetrics &aBoundingMetrics,
2257 + nsresult rv = NS_OK;
2258 + PangoLayout *layout = pango_layout_new(mPangoContext);
2260 + gchar *text = g_utf16_to_utf8(aString, aLength,
2261 + NULL, NULL, NULL);
2265 + NS_WARNING("nsFontMetricsPSPango::GetBoundingMetrics invalid unicode to follow");
2266 + DUMP_PRUNICHAR(aString, aLength)
2268 + aBoundingMetrics.leftBearing = 0;
2269 + aBoundingMetrics.rightBearing = 0;
2270 + aBoundingMetrics.width = 0;
2271 + aBoundingMetrics.ascent = 0;
2272 + aBoundingMetrics.descent = 0;
2274 + rv = NS_ERROR_FAILURE;
2278 + pango_layout_set_text(layout, text, -1);
2279 + FixupSpaceWidths(layout, text);
2281 + PangoLayoutLine *line;
2282 + if (pango_layout_get_line_count(layout) != 1) {
2283 + printf("Warning: more than one line!\n");
2285 + line = pango_layout_get_line(layout, 0);
2287 + // Get the ink and logical extents
2288 + PangoRectangle ink, logical;
2289 + pango_layout_line_get_extents(line, &ink, &logical);
2292 + P2T = mDeviceContext->DevUnitsToAppUnits();
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);
2302 + g_object_unref(layout);
2307 +#endif /* MOZ_MATHML */
2310 +nsFontMetricsPSPango::SetRightToLeftText(PRBool aIsRTL)
2313 + if (!mRTLPangoContext) {
2314 + mRTLPangoContext = get_context();
2315 + pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
2317 + pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
2318 + pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
2320 + mPangoContext = mRTLPangoContext;
2323 + mPangoContext = mLTRPangoContext;
2331 +nsFontMetricsPSPango::GetClusterInfo(const PRUnichar *aText,
2333 + PRUint8 *aClusterStarts)
2335 + nsresult rv = NS_OK;
2336 + PangoLogAttr *attrs = NULL;
2338 + PangoLayout *layout = pango_layout_new(mPangoContext);
2340 + // Convert the incoming UTF-16 to UTF-8
2341 + gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
2345 + NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2346 + DUMP_PRUNICHAR(aText, aLength)
2348 + rv = NS_ERROR_FAILURE;
2352 + // Set up the pango layout
2353 + pango_layout_set_text(layout, text, strlen(text));
2354 + FixupSpaceWidths(layout, text);
2356 + // Convert back to UTF-16 while filling in the cluster info
2358 + pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
2360 + for (PRUint32 pos = 0; pos < aLength; pos++) {
2361 + if (IS_HIGH_SURROGATE(aText[pos])) {
2362 + aClusterStarts[pos] = 1;
2366 + aClusterStarts[pos] = attrs[pos].is_cursor_position;
2376 + g_object_unref(layout);
2382 +nsFontMetricsPSPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
2387 + const gchar *curChar;
2388 + PRInt32 retval = 0;
2390 + float f = mDeviceContext->AppUnitsToDevUnits();
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);
2396 + // Convert the incoming UTF-16 to UTF-8
2397 + gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
2401 + NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2402 + DUMP_PRUNICHAR(aText, aLength)
2408 + // Set up the pango layout
2409 + pango_layout_set_text(layout, text, strlen(text));
2410 + FixupSpaceWidths(layout, text);
2412 + pango_layout_xy_to_index(layout, localX, localY,
2415 + // Convert the index back to the utf-16 index
2418 + for (PRUint32 curOffset=0; curOffset < aLength;
2419 + curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
2421 + // Check for a match before checking for a surrogate pair
2422 + if (curChar - text == inx) {
2423 + retval = curOffset;
2427 + if (IS_HIGH_SURROGATE(aText[curOffset]))
2431 + // If there was a trailing result, advance the index pointer the
2432 + // number of characters equal to the trailing result.
2433 + while (trailing) {
2435 + // Yes, this can make aInx > length to indicate the end of the
2437 + if (retval < (PRInt32)aLength && IS_HIGH_SURROGATE(aText[retval]))
2446 + g_object_unref(layout);
2452 +nsFontMetricsPSPango::GetRangeWidth(const PRUnichar *aText,
2458 + nsresult rv = NS_OK;
2459 + PRUint32 utf8Start = 0;
2460 + PRUint32 utf8End = 0;
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;
2470 + NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
2471 + DUMP_PRUNICHAR(aText, aLength)
2473 + rv = NS_ERROR_FAILURE;
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)) {
2481 + if (curOffset == aStart)
2482 + utf8Start = curChar - text;
2484 + if (curOffset == aEnd)
2485 + utf8End = curChar - text;
2487 + if (IS_HIGH_SURROGATE(aText[curOffset]))
2491 + // Special case where the end index is the same as the length
2492 + if (aLength == aEnd)
2493 + utf8End = strlen(text);
2495 + rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
2505 +nsFontMetricsPSPango::GetRangeWidth(const char *aText,
2511 + nsresult rv = NS_OK;
2512 + int *ranges = NULL;
2518 + PangoLayout *layout = pango_layout_new(mPangoContext);
2521 + rv = NS_ERROR_FAILURE;
2525 + pango_layout_set_text(layout, aText, aLength);
2526 + FixupSpaceWidths(layout, aText);
2528 + PangoLayoutLine *line;
2529 + if (pango_layout_get_line_count(layout) != 1) {
2530 + printf("Warning: more than one line!\n");
2532 + line = pango_layout_get_line(layout, 0);
2534 + pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
2536 + aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
2538 + f = mDeviceContext-> DevUnitsToAppUnits();
2539 + aWidth = nscoord(aWidth * f / PANGO_SCALE);
2545 + g_object_unref(layout);
2551 +nsFontMetricsPSPango::GetHints(void)
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);
2562 +nsFontMetricsPSPango::FamilyExists(nsIDeviceContext *aDevice,
2563 + const nsString &aName)
2565 + // fontconfig family name is always in UTF-8
2566 + NS_ConvertUTF16toUTF8 name(aName);
2568 + nsresult rv = NS_ERROR_FAILURE;
2569 + PangoContext *context = get_context();
2570 + PangoFontFamily **familyList;
2573 + pango_context_list_families(context, &familyList, &n);
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())) {
2584 + g_free(familyList);
2585 + g_object_unref(context);
2593 +nsFontMetricsPSPango::RealizeFont(void)
2595 + nsCString familyList;
2596 + // Create and fill out the font description.
2597 + mPangoFontDesc = pango_font_description_new();
2599 + // Add CSS names - walk the list of fonts, adding the generic as
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])
2607 + nsCString *familyName = mFontList.CStringAt(i);
2608 + familyList.Append(familyName->get());
2609 + familyList.Append(',');
2612 + // If there's a generic add a pref for the generic if there's one
2614 + if (mGenericFont && !mFont.systemFont) {
2616 + name += "font.name.";
2617 + name += mGenericFont->get();
2620 + nsString langGroup;
2621 + mLangGroup->ToString(langGroup);
2623 + name.AppendWithConversion(langGroup);
2625 + nsCOMPtr<nsIPref> pref;
2626 + pref = do_GetService(NS_PREF_CONTRACTID);
2629 + nsXPIDLCString value;
2630 + rv = pref->GetCharPref(name.get(), getter_Copies(value));
2632 + // we ignore prefs that have three hypens since they are X
2634 + if (NS_FFRECountHyphens(value) < 3) {
2636 + tmpstr.Append(value);
2638 + familyList.Append(tmpstr);
2639 + familyList.Append(',');
2644 + // Add the generic if there is one.
2645 + if (mGenericFont && !mFont.systemFont) {
2646 + familyList.Append(mGenericFont->get());
2647 + familyList.Append(',');
2651 + pango_font_description_set_family(mPangoFontDesc,
2652 + familyList.get());
2654 + // Set the point size
2655 + pango_font_description_set_size(mPangoFontDesc,
2656 + (gint)(mPointSize * PANGO_SCALE));
2659 + pango_font_description_set_style(mPangoFontDesc,
2660 + CalculateStyle(mFont.style));
2663 + pango_font_description_set_weight(mPangoFontDesc,
2664 + CalculateWeight(mFont.weight));
2666 + // Now that we have the font description set up, create the
2668 + mLTRPangoContext = get_context();
2669 + mPangoContext = mLTRPangoContext;
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);
2675 + // Set the pango language now that we have a context
2676 + pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
2678 + // And attach the font description to this context
2679 + pango_context_set_font_description(mPangoContext, mPangoFontDesc);
2686 +nsFontMetricsPSPango::EnumFontCallback(const nsString &aFamily,
2687 + PRBool aIsGeneric, void *aData)
2689 + NS_ConvertUTF16toUTF8 name(aFamily);
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);
2700 + metrics->mGenericFont =
2701 + metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1);
2702 + return PR_FALSE; // stop processing
2705 + return PR_TRUE; // keep processing
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!
2715 +nsFontMetricsPSPango::DrawStringSlowly(const gchar *aText,
2716 + const PRUnichar *aOrigString,
2719 + PangoLayoutLine *aLine,
2720 + const nscoord *aSpacing,
2721 + nsRenderingContextPS *aContext)
2724 + app2dev = mDeviceContext->AppUnitsToDevUnits();
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.
2737 + nscoord *utf8spacing = new nscoord[strlen(aText)];
2739 + if (aOrigString) {
2740 + const gchar *curChar = aText;
2741 + bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
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];
2748 + if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
2753 + memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
2758 + for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
2759 + tmpList = tmpList->next, curRun++) {
2760 + PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
2761 + gint tmpOffset = 0;
2763 + /* printf(" Rendering run %d: \"%s\"\n", curRun,
2764 + &aText[layoutRun->item->offset]); */
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));
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;
2778 + /* printf(" rendering at X coord %d\n", aX + offset); */
2779 + offset += tmpOffset;
2782 + draw_layout_line (aX, aY, aLine, this, aContext);
2784 + delete[] utf8spacing;
2788 +nsFontMetricsPSPango::GetTextDimensionsInternal(const gchar* aString,
2790 + PRInt32 aAvailWidth,
2792 + PRInt32 aNumBreaks,
2793 + nsTextDimensions& aDimensions,
2794 + PRInt32& aNumCharsFit,
2795 + nsTextDimensions& aLastWordDimensions)
2797 + NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
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
2805 + // Initialize OUT parameters
2806 + GetMaxAscent(aLastWordDimensions.ascent);
2807 + GetMaxDescent(aLastWordDimensions.descent);
2808 + aLastWordDimensions.width = -1;
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);
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
2822 + PRInt32 estimatedNumChars = 0;
2824 + if (aveCharWidth > 0)
2825 + estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
2827 + if (estimatedNumChars < 1)
2828 + estimatedNumChars = 1;
2830 + // Find the nearest break offset
2831 + PRInt32 estimatedBreakOffset = start + estimatedNumChars;
2832 + PRInt32 breakIndex;
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;
2843 + breakIndex = prevBreakState_BreakIndex;
2844 + while (((breakIndex + 1) < aNumBreaks) &&
2845 + (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
2849 + if (breakIndex == prevBreakState_BreakIndex) {
2850 + ++breakIndex; // make sure we advanced past the
2851 + // previous break index
2854 + numChars = aBreaks[breakIndex] - start;
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);
2864 + // See if the text fits
2865 + PRBool textFits = (twWidth + width) <= aAvailWidth;
2867 + // If the text fits then update the width and the number of
2868 + // characters that fit
2870 + aNumCharsFit += numChars;
2872 + start += numChars;
2874 + // This is a good spot to back up to if we need to so remember
2876 + prevBreakState_BreakIndex = breakIndex;
2877 + prevBreakState_Width = width;
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;
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;
2901 + // Repeatedly back up until we get to where the text
2902 + // fits or we're all the way back to the first word
2904 + while ((breakIndex >= 1) && (width > aAvailWidth)) {
2906 + start = aBreaks[breakIndex - 1];
2907 + numChars = aBreaks[breakIndex] - start;
2909 + if ((1 == numChars) && (aString[start] == ' '))
2910 + GetSpaceWidth(twWidth);
2911 + else if (numChars > 0)
2912 + GetWidth(&aString[start], numChars, twWidth);
2914 + aNumCharsFit = start;
2921 + aDimensions.width = width;
2922 + GetMaxAscent(aDimensions.ascent);
2923 + GetMaxDescent(aDimensions.descent);
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,
2934 +nsFontMetricsPSPango::FixupSpaceWidths (PangoLayout *aLayout,
2935 + const char *aString)
2937 + PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
2941 + for (GSList *tmpList = line->runs; tmpList && tmpList->data;
2942 + tmpList = tmpList->next, curRun++) {
2943 + PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
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;
2955 +GetPangoLanguage(nsIAtom *aLangGroup)
2957 + // Find the FC lang group for this lang group
2958 + nsCAutoString cname;
2959 + aLangGroup->ToUTF8String(cname);
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);
2966 + // if there's no lang group, just use the lang group as it was
2969 + // we're casting away the const here for the strings - should be
2972 + return pango_language_from_string(cname.get());
2973 + else if (langGroup->Lang)
2974 + return pango_language_from_string((char *) langGroup->Lang);
2976 + return pango_language_from_string("en");
2987 +CalculateStyle(PRUint8 aStyle)
2990 + case NS_FONT_STYLE_ITALIC:
2991 + return PANGO_STYLE_OBLIQUE;
2993 + case NS_FONT_STYLE_OBLIQUE:
2994 + return PANGO_STYLE_OBLIQUE;
2998 + return PANGO_STYLE_NORMAL;
3003 +CalculateWeight (PRUint16 aWeight)
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.
3013 + PRInt32 baseWeight = (aWeight + 50) / 100;
3014 + PRInt32 offset = aWeight - baseWeight * 100;
3016 + /* clip weights to range 0 to 9 */
3017 + if (baseWeight < 0)
3019 + if (baseWeight > 9)
3022 + /* Map from weight value to fcWeights index */
3023 + static int fcWeightLookup[10] = {
3024 + 0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
3027 + PRInt32 fcWeight = fcWeightLookup[baseWeight];
3030 + * adjust by the offset value, make sure we stay inside the
3033 + fcWeight += offset;
3040 + /* Map to final PANGO_WEIGHT value */
3041 + static int fcWeights[5] = {
3049 + return (PangoWeight)fcWeights[fcWeight];
3054 +EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric,
3055 + PRUint32* aCount, PRUnichar*** aResult)
3057 + FcPattern *pat = NULL;
3058 + FcObjectSet *os = NULL;
3059 + FcFontSet *fs = NULL;
3060 + nsresult rv = NS_ERROR_FAILURE;
3062 + PRUnichar **array = NULL;
3063 + PRUint32 narray = 0;
3064 + PRInt32 serif = 0, sansSerif = 0, monospace = 0, nGenerics;
3067 + *aResult = nsnull;
3069 + pat = FcPatternCreate();
3073 + os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, NULL);
3077 + // take the pattern and add the lang group to it
3079 + NS_AddLangGroup(pat, aLangGroup);
3081 + // get the font list
3082 + fs = FcFontList(0, pat, os);
3092 + // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
3093 + // "monospace", slightly different from CSS's 5.
3095 + serif = sansSerif = monospace = 1;
3096 + else if (!strcmp(aGeneric, "serif"))
3098 + else if (!strcmp(aGeneric, "sans-serif"))
3100 + else if (!strcmp(aGeneric, "monospace"))
3102 + else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
3103 + serif = sansSerif = 1;
3105 + NS_NOTREACHED("unexpected generic family");
3106 + nGenerics = serif + sansSerif + monospace;
3108 + array = NS_STATIC_CAST(PRUnichar **,
3109 + nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
3114 + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
3117 + array[narray++] = name;
3121 + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
3124 + array[narray++] = name;
3128 + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
3131 + array[narray++] = name;
3134 + for (int i=0; i < fs->nfont; ++i) {
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) {
3143 + // fontconfig always returns family names in UTF-8
3144 + PRUnichar* name = UTF8ToNewUnicode(nsDependentCString(family));
3149 + array[narray++] = name;
3152 + NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
3153 + CompareFontNames, nsnull);
3159 + nsMemory::Free(array);
3164 + if (NS_FAILED(rv) && array) {
3166 + nsMemory::Free (array[--narray]);
3167 + nsMemory::Free (array);
3170 + FcPatternDestroy(pat);
3172 + FcObjectSetDestroy(os);
3174 + FcFontSetDestroy(fs);
3181 +CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure)
3183 + const PRUnichar* str1 = *((const PRUnichar**) aArg1);
3184 + const PRUnichar* str2 = *((const PRUnichar**) aArg2);
3186 + return nsCRT::strcmp(str1, str2);
3190 +// nsFontEnumeratorPango class
3192 +nsFontEnumeratorPango::nsFontEnumeratorPango()
3196 +NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator)
3199 +nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount,
3200 + PRUnichar ***aResult)
3202 + NS_ENSURE_ARG_POINTER(aResult);
3203 + *aResult = nsnull;
3204 + NS_ENSURE_ARG_POINTER(aCount);
3207 + return EnumFontsPango(nsnull, nsnull, aCount, aResult);
3211 +nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup,
3212 + const char *aGeneric,
3214 + PRUnichar ***aResult)
3216 + NS_ENSURE_ARG_POINTER(aResult);
3217 + *aResult = nsnull;
3218 + NS_ENSURE_ARG_POINTER(aCount);
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;
3230 + return EnumFontsPango(langGroup, generic, aCount, aResult);
3234 +nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup,
3237 + NS_ENSURE_ARG_POINTER(aResult);
3238 + *aResult = PR_FALSE;
3239 + NS_ENSURE_ARG_POINTER(aLangGroup);
3241 + *aResult = PR_TRUE; // always return true for now.
3242 + // Finish me - ftang
3247 +nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup,
3248 + const char *aGeneric,
3249 + PRUnichar **aResult)
3251 + NS_ENSURE_ARG_POINTER(aResult);
3252 + *aResult = nsnull;
3254 + // Have a look at nsFontEnumeratorXft::GetDefaultFont for some
3255 + // possible code for this function.
3261 +nsFontEnumeratorPango::UpdateFontList(PRBool *_retval)
3263 + *_retval = PR_FALSE; // always return false for now
3266 Index: gfx/src/ps/nsFontMetricsPSPango.h
3267 ===================================================================
3268 RCS file: gfx/src/ps/nsFontMetricsPSPango.h
3269 diff -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
3273 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3274 +/* vim:expandtab:shiftwidth=4:tabstop=4:
3276 +/* ***** BEGIN LICENSE BLOCK *****
3277 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
3289 + * The Original Code is mozilla.org code.
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.
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.
3310 + * ***** END LICENSE BLOCK ***** */
3312 +#ifndef nsFontMetricsPSPango_h__
3313 +#define nsFontMetricsPSPango_h__
3315 +#include "nsIFontMetrics.h"
3316 +#include "nsIFontEnumerator.h"
3318 +#include "nsIAtom.h"
3319 +#include "nsString.h"
3320 +#include "nsVoidArray.h"
3321 +#include "nsFontMetricsPS.h"
3323 +#include <pango/pango.h>
3325 +class nsRenderingContextPS;
3326 +class nsIDrawingSurface;
3328 +class nsFontMetricsPSPango : public nsFontMetricsPS
3331 + nsFontMetricsPSPango();
3332 + virtual ~nsFontMetricsPSPango();
3334 + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
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);
3346 + NS_IMETHOD GetXHeight (nscoord& aResult)
3347 + { aResult = mXHeight; return NS_OK; };
3349 + NS_IMETHOD GetSuperscriptOffset (nscoord& aResult)
3350 + { aResult = mSuperscriptOffset;
3353 + NS_IMETHOD GetSubscriptOffset (nscoord& aResult)
3354 + { aResult = mSubscriptOffset;
3357 + NS_IMETHOD GetStrikeout (nscoord& aOffset, nscoord& aSize)
3358 + { aOffset = mStrikeoutOffset;
3359 + aSize = mStrikeoutSize;
3362 + NS_IMETHOD GetUnderline (nscoord& aOffset, nscoord& aSize)
3363 + { aOffset = mUnderlineOffset;
3364 + aSize = mUnderlineSize;
3367 + NS_IMETHOD GetHeight (nscoord &aHeight)
3368 + { aHeight = mMaxHeight;
3371 + NS_IMETHOD GetNormalLineHeight (nscoord &aHeight)
3372 + { aHeight = mEmHeight + mLeading;
3375 + NS_IMETHOD GetLeading (nscoord &aLeading)
3376 + { aLeading = mLeading;
3379 + NS_IMETHOD GetEmHeight (nscoord &aHeight)
3380 + { aHeight = mEmHeight;
3383 + NS_IMETHOD GetEmAscent (nscoord &aAscent)
3384 + { aAscent = mEmAscent;
3387 + NS_IMETHOD GetEmDescent (nscoord &aDescent)
3388 + { aDescent = mEmDescent;
3391 + NS_IMETHOD GetMaxHeight (nscoord &aHeight)
3392 + { aHeight = mMaxHeight;
3395 + NS_IMETHOD GetMaxAscent (nscoord &aAscent)
3396 + { aAscent = mMaxAscent;
3399 + NS_IMETHOD GetMaxDescent (nscoord &aDescent)
3400 + { aDescent = mMaxDescent;
3403 + NS_IMETHOD GetMaxAdvance (nscoord &aAdvance)
3404 + { aAdvance = mMaxAdvance;
3407 + NS_IMETHOD GetSpaceWidth (nscoord &aSpaceCharWidth)
3408 + { aSpaceCharWidth = mSpaceWidth;
3411 + NS_IMETHOD GetAveCharWidth (nscoord &aAveCharWidth)
3412 + { aAveCharWidth = mAveCharWidth;
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);
3419 + NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
3421 + NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
3424 + NS_IMETHOD GetTextDimensions(const char* aString,
3426 + nsTextDimensions& aDimensions);
3427 + NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
3429 + nsTextDimensions& aDimensions,
3430 + PRInt32* aFontID);
3431 + NS_IMETHOD GetTextDimensions(const char* aString,
3433 + PRInt32 aAvailWidth,
3435 + PRInt32 aNumBreaks,
3436 + nsTextDimensions& aDimensions,
3437 + PRInt32& aNumCharsFit,
3438 + nsTextDimensions& aLastWordDimensions,
3439 + PRInt32* aFontID);
3440 + NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
3442 + PRInt32 aAvailWidth,
3444 + PRInt32 aNumBreaks,
3445 + nsTextDimensions& aDimensions,
3446 + PRInt32& aNumCharsFit,
3447 + nsTextDimensions& aLastWordDimensions,
3448 + PRInt32* aFontID);
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,
3457 + const nscoord* aSpacing,
3458 + nsRenderingContextPS *aContext);
3461 + NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
3462 + nsBoundingMetrics &aBoundingMetrics);
3463 + NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString,
3465 + nsBoundingMetrics &aBoundingMetrics,
3466 + PRInt32 *aFontID);
3467 +#endif /* MOZ_MATHML */
3469 + NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
3471 + NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
3473 + PRUint8 *aClusterStarts);
3475 + virtual PRInt32 GetPosition(const PRUnichar *aText,
3479 + NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
3483 + PRUint32 &aWidth);
3485 + NS_IMETHOD GetRangeWidth(const char *aText,
3489 + PRUint32 &aWidth);
3491 + // get hints for the font
3492 + virtual PRUint32 GetHints (void);
3494 + // drawing surface methods
3495 + static nsresult FamilyExists (nsIDeviceContext *aDevice,
3496 + const nsString &aName);
3498 + inline nsIDeviceContext *GetDeviceContext() { return mDeviceContext; }
3502 + // generic font metrics class bits
3503 + nsCStringArray mFontList;
3504 + nsAutoVoidArray mFontIsGeneric;
3506 + nsIDeviceContext *mDeviceContext;
3507 + nsCOMPtr<nsIAtom> mLangGroup;
3508 + nsCString *mGenericFont;
3511 + nsCAutoString mDefaultFont;
3513 + // Pango-related items
3514 + PangoFontDescription *mPangoFontDesc;
3515 + PangoContext *mPangoContext;
3516 + PangoContext *mLTRPangoContext;
3517 + PangoContext *mRTLPangoContext;
3518 + PangoAttrList *mPangoAttrList;
3521 + // Cached font metrics
3523 + nscoord mSuperscriptOffset;
3524 + nscoord mSubscriptOffset;
3525 + nscoord mStrikeoutOffset;
3526 + nscoord mStrikeoutSize;
3527 + nscoord mUnderlineOffset;
3528 + nscoord mUnderlineSize;
3529 + nscoord mMaxHeight;
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;
3541 + // Private methods
3542 + nsresult RealizeFont(void);
3543 + nsresult CacheFontMetrics(void);
3545 + static PRBool EnumFontCallback(const nsString &aFamily,
3546 + PRBool aIsGeneric, void *aData);
3548 + void DrawStringSlowly(const gchar *aText,
3549 + const PRUnichar *aOrigString,
3552 + PangoLayoutLine *aLine,
3553 + const nscoord *aSpacing,
3554 + nsRenderingContextPS *aContext);
3556 + nsresult GetTextDimensionsInternal(const gchar* aString,
3558 + PRInt32 aAvailWidth,
3560 + PRInt32 aNumBreaks,
3561 + nsTextDimensions& aDimensions,
3562 + PRInt32& aNumCharsFit,
3563 + nsTextDimensions& aLastWordDimensions);
3565 + void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
3568 +class nsFontEnumeratorPango : public nsIFontEnumerator
3571 + nsFontEnumeratorPango();
3573 + NS_DECL_NSIFONTENUMERATOR
3578 Index: gfx/src/ps/nsPostScriptObj.cpp
3579 ===================================================================
3580 RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.cpp,v
3581 retrieving revision 1.124
3582 diff -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
3587 #if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
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)
3598 fputc('<', mScriptFP);
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));
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);
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");
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
3626 +nsPostScriptObj::show(const PangoGlyphString *glyphs, float zoom,
3627 + nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx)
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));
3636 + fputc('<', mScriptFP);
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)
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));
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);
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));
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);
3675 - fputs("> show\n", mScriptFP);
3679 @@ -2101,6 +2144,16 @@ nsPostScriptObj::moveto(nscoord x, nscoo
3681 /** ---------------------------------------------------
3682 * See documentation in nsPostScriptObj.h
3683 + * @update 10/20/06 behdad
3686 +nsPostScriptObj::rmoveto(nscoord x, nscoord y)
3688 + fprintf(mScriptFP, "%d %d rmoveto\n", x, y);
3691 +/** ---------------------------------------------------
3692 + * See documentation in nsPostScriptObj.h
3693 * @update 2/1/99 dwc
3696 Index: gfx/src/ps/nsPostScriptObj.h
3697 ===================================================================
3698 RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.h,v
3699 retrieving revision 1.47
3700 diff -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
3704 #include "nsIPersistentProperties2.h"
3705 #include "nsTempfilePS.h"
3706 #include "nsEPSObjectPS.h"
3707 +#ifdef MOZ_ENABLE_PANGO
3708 +#include <pango/pango.h>
3712 +class nsPSFontGenerator;
3715 +class nsValueArray;
3719 @@ -217,6 +223,14 @@ public:
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
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.
3734 @@ -346,12 +360,24 @@ public:
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
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
3756 + void show(const PangoGlyphString *glyphs, float zoom,
3757 + nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx);
3759 /** ---------------------------------------------------
3760 * set the clipping path to the current path using the winding rule
3761 * @update 2/1/99 dwc
3762 Index: gfx/src/ps/nsRenderingContextPS.cpp
3763 ===================================================================
3764 RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.cpp,v
3765 retrieving revision 1.83
3766 diff -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
3771 nsRenderingContextPS :: GetHints(PRUint32& aResult)
3773 + nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3774 + aResult = metrics->GetHints ();
3778 @@ -1006,8 +1008,11 @@ nsRenderingContextPS::GetTextDimensions(
3779 nsTextDimensions& aLastWordDimensions,
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);
3792 @@ -1021,43 +1026,31 @@ nsRenderingContextPS::GetTextDimensions(
3793 nsTextDimensions& aLastWordDimensions,
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);
3806 nsRenderingContextPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
3807 nsTextDimensions& aDimensions)
3809 - nsresult rv = NS_ERROR_FAILURE;
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);
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);
3827 nsRenderingContextPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
3828 nsTextDimensions& aDimensions, PRInt32* aFontID)
3830 - nsresult rv = NS_ERROR_FAILURE;
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);
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);
3848 /** ---------------------------------------------------
3849 @@ -1073,47 +1066,7 @@ nsRenderingContextPS :: DrawString(const
3851 nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3852 NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
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) {
3858 - nsCOMPtr<nsIAtom> langGroup;
3859 - mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
3860 - mPSObj->setlanggroup(langGroup);
3861 -#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
3867 - nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
3868 - NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
3869 - fontPS->SetupFont(this);
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);
3882 - // setup for following text
3883 - fontPS = fontThisChar;
3884 - fontPS->SetupFont(this);
3888 - // draw the last part
3889 - if (aLength-start)
3890 - DrawString(aString+start, aLength-start, aX, aY, fontPS,
3891 - aSpacing?aSpacing+start:nsnull);
3894 + return metrics->DrawString (aString, aLength, aX, aY, aSpacing, this);
3897 /** ---------------------------------------------------
3898 @@ -1129,110 +1082,7 @@ nsRenderingContextPS :: DrawString(const
3900 nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
3901 NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
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) {
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)
3914 - /* build up conversion table */
3915 - mPSObj->preshow(aString, aLength);
3919 - nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
3920 - NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
3921 - fontPS->SetupFont(this);
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);
3934 - // setup for following text
3935 - fontPS = fontThisChar;
3936 - fontPS->SetupFont(this);
3940 - // draw the last part
3941 - if (aLength-start)
3942 - DrawString(aString+start, aLength-start, aX, aY, fontPS,
3943 - aSpacing?aSpacing+start:nsnull);
3949 -nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength,
3950 - nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
3951 - const nscoord* aSpacing)
3953 - nscoord width = 0;
3957 - PRInt32 dxMem[500];
3961 - if (aLength > 500) {
3962 - dx0 = new PRInt32[aLength];
3963 - NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
3965 - mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0);
3968 - mTranMatrix->TransformCoord(&x, &y);
3969 - width = aFontPS->DrawString(this, x, y, aString, aLength);
3971 - if ((aSpacing) && (dx0 != dxMem)) {
3980 -nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength,
3981 - nscoord aX, nscoord aY, nsFontPS* aFontPS,
3982 - const nscoord* aSpacing)
3984 - nscoord width = 0;
3989 - // Slow, but accurate rendering
3990 - const PRUnichar* end = aString + aLength;
3991 - while (aString < end){
3994 - mTranMatrix->TransformCoord(&x, &y);
3995 - aFontPS->DrawString(this, x, y, aString, 1);
3996 - aX += *aSpacing++;
4001 - mTranMatrix->TransformCoord(&x, &y);
4002 - width = aFontPS->DrawString(this, x, y, aString, aLength);
4006 + return metrics->DrawString (aString, aLength, aX, aY, aFontID, aSpacing, this);
4009 /** ---------------------------------------------------
4010 @@ -1346,8 +1196,10 @@ nsRenderingContextPS::GetBoundingMetrics
4012 nsBoundingMetrics& aBoundingMetrics)
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);
4023 @@ -1359,8 +1211,10 @@ nsRenderingContextPS::GetBoundingMetrics
4024 nsBoundingMetrics& aBoundingMetrics,
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);
4034 #endif /* MOZ_MATHML */
4036 Index: gfx/src/ps/nsRenderingContextPS.h
4037 ===================================================================
4038 RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.h,v
4039 retrieving revision 1.49
4040 diff -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);
4047 + nsTransform2D *GetTranMatrix() {
4048 + return mTranMatrix;
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,
4057 const nscoord* aSpacing);
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);
4067 NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
4068 Index: gfx/src/ps/nsType1.cpp
4069 ===================================================================
4070 RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.cpp,v
4071 retrieving revision 1.5.8.1
4072 diff -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
4076 #include "nsIFreeType2.h"
4077 #include "nsServiceManagerUtils.h"
4079 +#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4080 +#include FT_TYPE1_TABLES_H
4082 #include "nsPrintfCString.h"
4083 #include "nsAutoBuffer.h"
4084 +#include "nsValueArray.h"
4085 +#include "nsVoidArray.h"
4087 #define HEXASCII_LINE_LEN 64
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,
4094 + const char *aGlyphName);
4095 static void flattenName(nsCString& aString);
4097 /* thunk a short name for this function */
4098 @@ -202,19 +207,30 @@ Type1EncryptString(unsigned char *aInBuf
4099 aOutBuf[i] = Type1Encrypt(aInBuf[i], &key);
4103 +get_upm (FT_Face face)
4105 + FT_UShort upm = face->units_per_EM;
4108 + upm = 1000; // bitmap font or something
4114 sideWidthAndBearing(const FT_Vector *aEndPt, FT2PT1_info *aFti)
4118 - FT_UShort upm = aFti->face->units_per_EM;
4119 + FT_UShort upm = get_upm (aFti->face);
4124 slot = aFti->face->glyph;
4126 -#ifdef MOZ_ENABLE_XFT
4127 +#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4128 FT_Error error = FT_Get_Glyph(slot, &glyph);
4130 NS_ERROR("sideWidthAndBearing failed to get glyph");
4131 @@ -256,7 +272,7 @@ static int
4132 moveto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
4134 FT2PT1_info *fti = (FT2PT1_info *)aClosure;
4135 - FT_UShort upm = fti->face->units_per_EM;
4136 + FT_UShort upm = get_upm (fti->face);
4139 if (fti->elm_cnt == 0) {
4140 @@ -293,7 +309,7 @@ static int
4141 lineto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
4143 FT2PT1_info *fti = (FT2PT1_info *)aClosure;
4144 - FT_UShort upm = fti->face->units_per_EM;
4145 + FT_UShort upm = get_upm (fti->face);
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
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)
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;
4166 cur_x = ftinfo->cur_x;
4167 @@ -408,8 +424,55 @@ static FT_Outline_Funcs ft_outline_funcs
4173 +trace_bitmap_glyph (FT_GlyphSlot slot, FT2PT1_info *fti)
4175 + unsigned char *row, *byte_ptr, byte;
4177 + int x, y, bit_mask;
4178 + int upm, x_off, y_off, x_mult, y_mult;
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;
4186 + switch (slot->bitmap.pixel_mode) {
4187 + case FT_PIXEL_MODE_MONO:
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--) {
4192 + for (bit_mask = 128; bit_mask && x < slot->bitmap.width; bit_mask >>= 1, x++) {
4193 + if (byte & bit_mask) {
4195 + p.x = x_mult * (x_off + x);
4196 + p.y = y_mult * (y_off - y);
4197 + moveto(&p, (void *) fti);
4199 + lineto(&p, (void *) fti);
4201 + lineto(&p, (void *) fti);
4203 + lineto(&p, (void *) fti);
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)
4224 @@ -423,7 +486,7 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4225 unsigned char *start = aBuf;
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);
4232 NS_ERROR("failed to load aGlyphID");
4233 @@ -438,11 +501,6 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4235 slot = aFace->glyph;
4237 - if (slot->format != ft_glyph_format_outline) {
4238 - NS_ERROR("aGlyphID is not an outline glyph");
4242 #ifdef MOZ_ENABLE_FREETYPE2
4245 @@ -456,18 +514,27 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4246 for (j=0; j< aLenIV; j++) {
4247 fti.len += ecsi(&fti.buf, 0);
4249 -#ifdef MOZ_ENABLE_XFT
4250 - if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) {
4251 - NS_ERROR("error decomposing aGlyphID");
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");
4262 - rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
4263 - if (NS_FAILED(rv)) {
4264 - NS_ERROR("error decomposing aGlyphID");
4267 + rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
4268 + if (NS_FAILED(rv)) {
4269 + NS_ERROR("error decomposing aGlyphID");
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");
4278 + NS_ERROR("aGlyphID has unhandled format");
4282 fti.len += csc(&fti.buf, T1_CLOSEPATH);
4283 @@ -491,28 +558,52 @@ FT2GlyphToType1CharString(nsIFreeType2 *
4287 -#ifdef MOZ_ENABLE_XFT
4288 +#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4289 outputType1SubFont(FT_Face aFace,
4291 outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
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);
4301 FT2ToType1FontName(FT_Face aFace, int aWmode, nsCString& aFontName)
4303 + // only hash the first 10 000 bytes of the font
4304 + int size = aFace->stream->size;
4305 + size = size > 10000 ? 10000 : size;
4307 + unsigned char *data;
4308 + if (aFace->stream->read) {
4309 + data = (unsigned char *) malloc (size);
4310 + aFace->stream->read (aFace->stream, 0, data, size);
4312 + data = aFace->stream->base;
4315 + unsigned int data_hash = 0;
4317 + for (i = 0; i < size; i++)
4318 + data_hash = (data_hash << 5) - data_hash + data[size];
4320 + if (aFace->stream->read)
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);
4334 // output a subsetted truetype font converted to multiple type 1 fonts
4336 -FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset,
4337 +FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset,
4338 int aWmode, FILE *aFile)
4340 #ifdef MOZ_ENABLE_FREETYPE2
4341 @@ -527,32 +618,35 @@ FT2SubsetToType1FontSet(FT_Face aFace, c
4342 nsCAutoString fontNameBase;
4343 FT2ToType1FontName(aFace, aWmode, fontNameBase);
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,
4354 outputType1SubFont(ft2, aFace,
4356 - Substring(aSubset, i * 255, PR_MIN(255, aSubset.Length() - i * 255)),
4357 - fontName.get(), aWmode, 4, aFile);
4359 + (i * 255), PR_MIN(255, aGlyphSubset->Count() - i * 255),
4360 + fontName.get(), aWmode, 4, aFile);
4365 // output a type 1 font (with 255 characters or fewer)
4367 -#ifdef MOZ_ENABLE_XFT
4368 +#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
4369 outputType1SubFont(FT_Face aFace,
4371 outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
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)
4380 - FT_UShort upm = aFace->units_per_EM;
4381 + FT_UShort upm = get_upm (aFace);
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));
4389 - nsString charIDstr(aCharIDs);
4390 - PRUint32 len = aCharIDs.Length();
4392 + nsValueArray glyphs(PR_UINT16_MAX);
4393 + nsCStringArray glyphnames(PR_UINT16_MAX);
4394 + glyphs = *aGlyphs;
4396 + PRUint32 len = aLen;
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
4406 - charIDstr.AppendLiteral("1234567890");
4407 + for (i = 1; i <= 10; i++) {
4408 + glyphs.AppendValue(i);
4413 - const PRUnichar *charIDs = charIDstr.get();
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);
4420 + has_glyph_name = aFt2->hasPSGlyphNames(aFace);
4423 // construct an Encoding vector : the 0th element
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) {
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
4440 + NS_FAILED(aFt2->getGlyphName(aFace, glyphs.ValueAt(i), buffer, 255))
4443 + name = nsPrintfCString(256, "/idx%04X", glyphs.ValueAt(i));
4445 + name = nsPrintfCString(256, "/%s", buffer);
4447 + glyphnames.AppendCString(name);
4448 + fprintf(aFile, name.get());
4449 + if ((i-aOffset) % 8 == 6) fputc('\n', aFile);
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);
4458 fputs("] def\n", aFile);
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);
4468 FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, nsnull);
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)
4479 - FT2GlyphToType1CharString(aFace, glyphID, aWmode, aLenIV, nsnull);
4480 + FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, aLenIV,
4483 - aFt2->GetCharIndex(aFace, charIDs[i], &glyphID);
4485 - FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, aLenIV, nsnull);
4486 + FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), aWmode, aLenIV,
4490 if (charStringLen > maxCharStringLen)
4491 @@ -666,7 +784,7 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
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,
4500 @@ -676,22 +794,20 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
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");
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());
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());
4524 charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()),
4525 - charStringLen, charIDs[i]);
4526 + charStringLen, glyphnames.CStringAt(i - aOffset)->get());
4529 // wrap up the encrypted part of the font definition
4530 @@ -753,15 +869,12 @@ void encryptAndHexOut(FILE *aFile, PRUin
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)
4537 // use a local buffer instead of nsPrintfCString to avoid alloc.
4541 - oLen = PR_snprintf(buf, 30, "/.notdef %d RD ", aLen);
4543 - oLen = PR_snprintf(buf, 30, "/uni%04X %d RD ", aId, aLen);
4544 + oLen = PR_snprintf(buf, 30, "%s %d RD ", aGlyphName, aLen);
4547 NS_WARNING("buffer size exceeded. charstring will be truncated");
4548 Index: gfx/src/ps/nsType1.h
4549 ===================================================================
4550 RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.h,v
4551 retrieving revision 1.5
4552 diff -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
4559 +class nsValueArray;
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);
4566 Index: 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
4574 +freetype/t1tables.h
4579 pango/pangofc-fontmap.h
4580 pango/pango-fontmap.h