3086 lines
99 KiB
Diff
3086 lines
99 KiB
Diff
--- mozilla/config/autoconf.mk.in.foo 2004-11-22 12:55:08.000000000 -0500
|
|
+++ mozilla/config/autoconf.mk.in 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -394,6 +394,10 @@
|
|
MOZ_XFT_LIBS = @MOZ_XFT_LIBS@
|
|
MOZ_ENABLE_COREXFONTS = @MOZ_ENABLE_COREXFONTS@
|
|
|
|
+MOZ_ENABLE_PANGO = @MOZ_ENABLE_PANGO@
|
|
+MOZ_PANGO_CFLAGS = @MOZ_PANGO_CFLAGS@
|
|
+MOZ_PANGO_LIBS = @MOZ_PANGO_LIBS@
|
|
+
|
|
MOZ_EXTRA_X11CONVERTERS = @MOZ_EXTRA_X11CONVERTERS@
|
|
|
|
MOZ_ENABLE_XINERAMA = @MOZ_ENABLE_XINERAMA@
|
|
--- mozilla/gfx/src/gtk/nsGfxFactoryGTK.cpp.foo 2003-09-07 18:20:38.000000000 -0400
|
|
+++ mozilla/gfx/src/gtk/nsGfxFactoryGTK.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -62,6 +62,9 @@
|
|
#ifdef NATIVE_THEME_SUPPORT
|
|
#include "nsNativeThemeGTK.h"
|
|
#endif
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+#include "nsFontMetricsPango.h"
|
|
+#endif
|
|
#ifdef MOZ_ENABLE_XFT
|
|
#include "nsFontMetricsXft.h"
|
|
#endif
|
|
@@ -112,6 +115,13 @@
|
|
if (aOuter)
|
|
return NS_ERROR_NO_AGGREGATION;
|
|
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ if (NS_IsPangoEnabled()) {
|
|
+ result = new nsFontMetricsPango();
|
|
+ if (!result)
|
|
+ return NS_ERROR_OUT_OF_MEMORY;
|
|
+ } else {
|
|
+#endif
|
|
#ifdef MOZ_ENABLE_XFT
|
|
if (NS_IsXftEnabled()) {
|
|
result = new nsFontMetricsXft();
|
|
@@ -127,6 +137,9 @@
|
|
#ifdef MOZ_ENABLE_XFT
|
|
}
|
|
#endif
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ }
|
|
+#endif
|
|
|
|
NS_ADDREF(result);
|
|
nsresult rv = result->QueryInterface(aIID, aResult);
|
|
@@ -148,6 +161,13 @@
|
|
if (aOuter)
|
|
return NS_ERROR_NO_AGGREGATION;
|
|
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ if (NS_IsPangoEnabled()) {
|
|
+ result = new nsFontEnumeratorPango();
|
|
+ if (!result)
|
|
+ return NS_ERROR_OUT_OF_MEMORY;
|
|
+ } else {
|
|
+#endif
|
|
#ifdef MOZ_ENABLE_XFT
|
|
if (NS_IsXftEnabled()) {
|
|
result = new nsFontEnumeratorXft();
|
|
@@ -163,6 +183,9 @@
|
|
#ifdef MOZ_ENABLE_XFT
|
|
}
|
|
#endif
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ }
|
|
+#endif
|
|
|
|
NS_ADDREF(result);
|
|
nsresult rv = result->QueryInterface(aIID, aResult);
|
|
--- mozilla/gfx/src/gtk/mozilla-decoder.h.foo 2004-11-22 12:56:21.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/mozilla-decoder.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -0,0 +1,72 @@
|
|
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
+/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
+ */
|
|
+/* ***** BEGIN LICENSE BLOCK *****
|
|
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
+ *
|
|
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
+ * the License. You may obtain a copy of the License at
|
|
+ * http://www.mozilla.org/MPL/
|
|
+ *
|
|
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
+ * for the specific language governing rights and limitations under the
|
|
+ * License.
|
|
+ *
|
|
+ * The Original Code is mozilla.org code.
|
|
+ *
|
|
+ * The Initial Developer of the Original Code is Christopher Blizzard
|
|
+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
|
|
+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
|
+ *
|
|
+ * Contributor(s):
|
|
+ *
|
|
+ * Alternatively, the contents of this file may be used under the terms of
|
|
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
+ * of those above. If you wish to allow use of your version of this file only
|
|
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
+ * use your version of this file under the terms of the MPL, indicate your
|
|
+ * decision by deleting the provisions above and replace them with the notice
|
|
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
+ * the provisions above, a recipient may use your version of this file under
|
|
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
+ *
|
|
+ * ***** END LICENSE BLOCK ***** */
|
|
+
|
|
+#ifndef _MOZILLA_DECODER_H
|
|
+#define _MOZILLA_DECODER_H
|
|
+
|
|
+#include <pango/pangofc-decoder.h>
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+#define MOZILLA_TYPE_DECODER (mozilla_decoder_get_type())
|
|
+#define MOZILLA_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaDecoder))
|
|
+#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER))
|
|
+
|
|
+typedef struct _MozillaDecoder MozillaDecoder;
|
|
+typedef struct _MozillaDecoderClass MozillaDecoderClass;
|
|
+
|
|
+#define MOZILLA_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
|
|
+#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER))
|
|
+#define MOZILLA_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
|
|
+
|
|
+struct _MozillaDecoder
|
|
+{
|
|
+ PangoFcDecoder parent_instance;
|
|
+};
|
|
+
|
|
+struct _MozillaDecoderClass
|
|
+{
|
|
+ PangoFcDecoderClass parent_class;
|
|
+};
|
|
+
|
|
+GType mozilla_decoder_get_type (void);
|
|
+int mozilla_decoders_init (void);
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*_MOZILLA_DECODER_H */
|
|
--- mozilla/gfx/src/gtk/mozilla-decoder.cpp.foo 2004-11-22 12:56:21.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/mozilla-decoder.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -0,0 +1,376 @@
|
|
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
+/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
+ */
|
|
+/* ***** BEGIN LICENSE BLOCK *****
|
|
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
+ *
|
|
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
+ * the License. You may obtain a copy of the License at
|
|
+ * http://www.mozilla.org/MPL/
|
|
+ *
|
|
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
+ * for the specific language governing rights and limitations under the
|
|
+ * License.
|
|
+ *
|
|
+ * The Original Code is mozilla.org code.
|
|
+ *
|
|
+ * The Initial Developer of the Original Code is Christopher Blizzard
|
|
+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
|
|
+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
|
+ *
|
|
+ * Contributor(s):
|
|
+ *
|
|
+ * Alternatively, the contents of this file may be used under the terms of
|
|
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
+ * of those above. If you wish to allow use of your version of this file only
|
|
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
+ * use your version of this file under the terms of the MPL, indicate your
|
|
+ * decision by deleting the provisions above and replace them with the notice
|
|
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
+ * the provisions above, a recipient may use your version of this file under
|
|
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
+ *
|
|
+ * ***** END LICENSE BLOCK ***** */
|
|
+
|
|
+#define PANGO_ENABLE_BACKEND
|
|
+#define PANGO_ENABLE_ENGINE
|
|
+
|
|
+#include "mozilla-decoder.h"
|
|
+#include <pango/pangoxft.h>
|
|
+#include <pango/pangofc-fontmap.h>
|
|
+#include <pango/pangofc-font.h>
|
|
+#include <gdk/gdkx.h>
|
|
+
|
|
+#include "nsString.h"
|
|
+#include "nsIPersistentProperties2.h"
|
|
+#include "nsNetUtil.h"
|
|
+#include "nsReadableUtils.h"
|
|
+#include "nsICharsetConverterManager.h"
|
|
+#include "nsICharRepresentable.h"
|
|
+#include "nsCompressedCharMap.h"
|
|
+
|
|
+#undef DEBUG_CUSTOM_ENCODER
|
|
+
|
|
+G_DEFINE_TYPE (MozillaDecoder, mozilla_decoder, PANGO_TYPE_FC_DECODER)
|
|
+
|
|
+MozillaDecoder *mozilla_decoder_new (void);
|
|
+
|
|
+static FcCharSet *mozilla_decoder_get_charset (PangoFcDecoder *decoder,
|
|
+ PangoFcFont *fcfont);
|
|
+static PangoGlyph mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
|
|
+ PangoFcFont *fcfont,
|
|
+ guint32 wc);
|
|
+
|
|
+static PangoFcDecoder *mozilla_find_decoder (FcPattern *pattern,
|
|
+ gpointer user_data);
|
|
+
|
|
+typedef struct _MozillaDecoderPrivate MozillaDecoderPrivate;
|
|
+
|
|
+#define MOZILLA_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderPrivate))
|
|
+
|
|
+struct _MozillaDecoderPrivate {
|
|
+ char *family;
|
|
+ char *encoder;
|
|
+ char *cmap;
|
|
+ gboolean is_wide;
|
|
+ FcCharSet *charset;
|
|
+ nsCOMPtr<nsIUnicodeEncoder> uEncoder;
|
|
+};
|
|
+
|
|
+static nsICharsetConverterManager *gCharsetManager = NULL;
|
|
+
|
|
+static NS_DEFINE_CID(kCharsetConverterManagerCID,
|
|
+ NS_ICHARSETCONVERTERMANAGER_CID);
|
|
+
|
|
+// Hash tables that hold the custom encodings and custom cmaps used in
|
|
+// various fonts.
|
|
+GHashTable *encoder_hash = NULL;
|
|
+GHashTable *cmap_hash = NULL;
|
|
+GHashTable *wide_hash = NULL;
|
|
+
|
|
+void
|
|
+mozilla_decoder_init (MozillaDecoder *decoder)
|
|
+{
|
|
+}
|
|
+
|
|
+void
|
|
+mozilla_decoder_class_init (MozillaDecoderClass *klass)
|
|
+{
|
|
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
+ PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
|
|
+
|
|
+ /* object_class->finalize = test_finalize; */
|
|
+
|
|
+ parent_class->get_charset = mozilla_decoder_get_charset;
|
|
+ parent_class->get_glyph = mozilla_decoder_get_glyph;
|
|
+
|
|
+ g_type_class_add_private (object_class, sizeof (MozillaDecoderPrivate));
|
|
+}
|
|
+
|
|
+MozillaDecoder *
|
|
+mozilla_decoder_new(void)
|
|
+{
|
|
+ return (MozillaDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
|
|
+}
|
|
+
|
|
+#ifdef DEBUG_CUSTOM_ENCODER
|
|
+void
|
|
+dump_hash(char *key, char *val, void *arg)
|
|
+{
|
|
+ printf("%s -> %s\n", key, val);
|
|
+}
|
|
+#endif
|
|
+
|
|
+/**
|
|
+ * mozilla_decoders_init:
|
|
+ *
|
|
+ * #mozilla_decoders_init:
|
|
+ *
|
|
+ * This initializes all of the application-specific custom decoders
|
|
+ * that Mozilla uses. This should only be called once during the
|
|
+ * lifetime of the application.
|
|
+ *
|
|
+ * Return value: zero on success, not zero on failure.
|
|
+ *
|
|
+ **/
|
|
+
|
|
+int
|
|
+mozilla_decoders_init(void)
|
|
+{
|
|
+ static PRBool initialized = PR_FALSE;
|
|
+ if (initialized)
|
|
+ return 0;
|
|
+
|
|
+ encoder_hash = g_hash_table_new(g_str_hash, g_str_equal);
|
|
+ cmap_hash = g_hash_table_new(g_str_hash, g_str_equal);
|
|
+ wide_hash = g_hash_table_new(g_str_hash, g_str_equal);
|
|
+
|
|
+ PRBool dumb = PR_FALSE;
|
|
+ nsCOMPtr<nsIPersistentProperties> props;
|
|
+ nsCOMPtr<nsISimpleEnumerator> encodeEnum;
|
|
+
|
|
+ NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
|
|
+ NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
|
|
+
|
|
+ if (!props)
|
|
+ goto loser;
|
|
+
|
|
+ // Enumerate the properties in this file and figure out all of the
|
|
+ // fonts for which we have custom encodings.
|
|
+ props->Enumerate(getter_AddRefs(encodeEnum));
|
|
+ if (!encodeEnum)
|
|
+ goto loser;
|
|
+
|
|
+ while (encodeEnum->HasMoreElements(&dumb), dumb) {
|
|
+ nsCOMPtr<nsIPropertyElement> prop;
|
|
+ encodeEnum->GetNext(getter_AddRefs(prop));
|
|
+ if (!prop)
|
|
+ goto loser;
|
|
+
|
|
+ nsCAutoString name;
|
|
+ prop->GetKey(name);
|
|
+ nsAutoString value;
|
|
+ prop->GetValue(value);
|
|
+
|
|
+ if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
|
|
+ printf("string doesn't begin with encoding?\n");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ name = Substring(name, 9);
|
|
+
|
|
+ if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
|
|
+ name = Substring(name, 0, name.Length() - 4);
|
|
+
|
|
+ // Strip off a .wide if it's there.
|
|
+ if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) {
|
|
+ g_hash_table_insert(wide_hash, g_strdup(name.get()),
|
|
+ g_strdup("wide"));
|
|
+ value = Substring(value, 0, name.Length() - 5);
|
|
+ }
|
|
+
|
|
+ g_hash_table_insert(encoder_hash,
|
|
+ g_strdup(name.get()),
|
|
+ g_strdup(NS_ConvertUTF16toUTF8(value).get()));
|
|
+ }
|
|
+ else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) {
|
|
+ name = Substring(name, 0, name.Length() - 7);
|
|
+ g_hash_table_insert(cmap_hash,
|
|
+ g_strdup(name.get()),
|
|
+ g_strdup(NS_ConvertUTF16toUTF8(value).get()));
|
|
+ }
|
|
+ else {
|
|
+ printf("unknown suffix used for mapping\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(pango_xft_get_font_map(GDK_DISPLAY(),gdk_x11_get_default_screen())),
|
|
+ mozilla_find_decoder,
|
|
+ NULL,
|
|
+ NULL);
|
|
+
|
|
+ initialized = PR_TRUE;
|
|
+
|
|
+#ifdef DEBUG_CUSTOM_ENCODER
|
|
+ printf("*** encoders\n");
|
|
+ g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
|
|
+
|
|
+ printf("*** cmaps\n");
|
|
+ g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
|
|
+#endif
|
|
+
|
|
+ return 0;
|
|
+
|
|
+ loser:
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+FcCharSet *
|
|
+mozilla_decoder_get_charset (PangoFcDecoder *decoder,
|
|
+ PangoFcFont *fcfont)
|
|
+{
|
|
+ MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
|
|
+
|
|
+ if (priv->charset)
|
|
+ return priv->charset;
|
|
+
|
|
+ // First time this has been accessed. Populate the charset.
|
|
+ priv->charset = FcCharSetCreate();
|
|
+
|
|
+ if (!gCharsetManager) {
|
|
+ nsServiceManager::GetService(kCharsetConverterManagerCID,
|
|
+ NS_GET_IID(nsICharsetConverterManager), (nsISupports**)&gCharsetManager);
|
|
+ }
|
|
+
|
|
+ nsCOMPtr<nsIUnicodeEncoder> encoder;
|
|
+ nsCOMPtr<nsICharRepresentable> represent;
|
|
+
|
|
+ if (!gCharsetManager)
|
|
+ goto end;
|
|
+
|
|
+ gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
|
|
+ if (!encoder)
|
|
+ goto end;
|
|
+
|
|
+ encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
|
|
+
|
|
+ priv->uEncoder = encoder;
|
|
+
|
|
+ represent = do_QueryInterface(encoder);
|
|
+ if (!represent)
|
|
+ goto end;
|
|
+
|
|
+ PRUint32 map[UCS2_MAP_LEN];
|
|
+ memset(map, 0, sizeof(map));
|
|
+
|
|
+ represent->FillInfo(map);
|
|
+
|
|
+ for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
|
|
+ if (IS_REPRESENTABLE(map, i))
|
|
+ FcCharSetAddChar(priv->charset, i);
|
|
+ }
|
|
+
|
|
+ end:
|
|
+ return priv->charset;
|
|
+}
|
|
+
|
|
+PangoGlyph
|
|
+mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
|
|
+ PangoFcFont *fcfont,
|
|
+ guint32 wc)
|
|
+{
|
|
+ MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
|
|
+
|
|
+ PangoGlyph retval = 0;
|
|
+ PRUnichar inchar = wc;
|
|
+ PRInt32 inlen = 1;
|
|
+ char outchar[2] = {0,0};
|
|
+ PRInt32 outlen = 2;
|
|
+
|
|
+ priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
|
|
+ if (outlen != 1) {
|
|
+ printf("Warning: mozilla_decoder_get_glyph doesn't support more than one character conversions.\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ FT_Face face = pango_fc_font_lock_face(fcfont);
|
|
+
|
|
+#ifdef DEBUG_CUSTOM_ENCODER
|
|
+ char *filename;
|
|
+ FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
|
|
+ printf("filename is %s\n", filename);
|
|
+#endif
|
|
+
|
|
+ // Make sure to set the right charmap before trying to get the
|
|
+ // glyph
|
|
+ if (priv->cmap) {
|
|
+ if (!strcmp(priv->cmap, "mac_roman")) {
|
|
+ FT_Select_Charmap(face, ft_encoding_apple_roman);
|
|
+ }
|
|
+ else if (!strcmp(priv->cmap, "unicode")) {
|
|
+ FT_Select_Charmap(face, ft_encoding_unicode);
|
|
+ }
|
|
+ else {
|
|
+ printf("Warning: Invalid charmap entry for family %s\n",
|
|
+ priv->family);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Standard 8 bit to glyph translation
|
|
+ if (!priv->is_wide) {
|
|
+ FcChar32 blah = PRUint8(outchar[0]);
|
|
+ retval = FT_Get_Char_Index(face, blah);
|
|
+#ifdef DEBUG_CUSTOM_ENCODER
|
|
+ printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n",
|
|
+ wc, outchar[0], blah, retval, (void *)face);
|
|
+#endif
|
|
+ }
|
|
+ else {
|
|
+ printf("Warning: We don't support .wide fonts!\n");
|
|
+ retval = 0;
|
|
+ }
|
|
+
|
|
+ pango_fc_font_unlock_face(fcfont);
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+PangoFcDecoder *
|
|
+mozilla_find_decoder (FcPattern *pattern, gpointer user_data)
|
|
+{
|
|
+ // Compare the family name of the font that's been opened to see
|
|
+ // if we have a custom decoder.
|
|
+ const char *orig = NULL;
|
|
+ FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig);
|
|
+
|
|
+ nsCAutoString family;
|
|
+ family.Assign(orig);
|
|
+
|
|
+ family.StripWhitespace();
|
|
+ ToLowerCase(family);
|
|
+
|
|
+ char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
|
|
+ if (!encoder)
|
|
+ return NULL;
|
|
+
|
|
+ MozillaDecoder *decoder = mozilla_decoder_new();
|
|
+
|
|
+ MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
|
|
+
|
|
+ priv->family = g_strdup(family.get());
|
|
+ priv->encoder = g_strdup(encoder);
|
|
+
|
|
+ char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
|
|
+ if (cmap)
|
|
+ priv->cmap = g_strdup(cmap);
|
|
+
|
|
+ char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
|
|
+ if (wide)
|
|
+ priv->is_wide = TRUE;
|
|
+
|
|
+ return PANGO_FC_DECODER(decoder);
|
|
+}
|
|
--- mozilla/gfx/src/gtk/gfxgtk.pkg.foo 2004-01-06 20:21:35.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/gfxgtk.pkg 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -7,3 +7,6 @@
|
|
#if MOZ_ENABLE_XFT
|
|
dist/bin/res/fonts/fontEncoding.properties
|
|
#endif
|
|
+#if MOZ_ENABLE_PANGO
|
|
+dist/bin/res/fonts/pangoFontEncoding.properties
|
|
+#endif
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsXft.cpp.foo 2004-10-14 16:36:14.000000000 -0400
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsXft.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -238,7 +238,7 @@
|
|
|
|
static int CalculateSlant (PRUint8 aStyle);
|
|
static int CalculateWeight (PRUint16 aWeight);
|
|
-static void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
|
|
+/* static */ void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
|
|
static void AddFFRE (FcPattern *aPattern, nsCString *aFamily,
|
|
PRBool aWeak);
|
|
static void FFREToFamily (nsACString &aFFREName, nsACString &oFamily);
|
|
@@ -449,7 +449,7 @@
|
|
// Make sure that the pixel size is at least greater than zero
|
|
if (mPixelSize < 1) {
|
|
#ifdef DEBUG
|
|
- printf("*** Warning: nsFontMetricsXft was passed a pixel size of %d\n",
|
|
+ printf("*** Warning: nsFontMetricsXft was passed a pixel size of %f\n",
|
|
mPixelSize);
|
|
#endif
|
|
mPixelSize = 1;
|
|
@@ -474,6 +474,26 @@
|
|
if (NS_FAILED(RealizeFont()))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("%i\n", mXHeight);
|
|
+ printf("%i\n", mSuperscriptOffset);
|
|
+ printf("%i\n", mSubscriptOffset);
|
|
+ printf("%i\n", mStrikeoutOffset);
|
|
+ printf("%i\n", mStrikeoutSize);
|
|
+ printf("%i\n", mUnderlineOffset);
|
|
+ printf("%i\n", mUnderlineSize);
|
|
+ printf("%i\n", mMaxHeight);
|
|
+ printf("%i\n", mLeading);
|
|
+ printf("%i\n", mEmHeight);
|
|
+ printf("%i\n", mEmAscent);
|
|
+ printf("%i\n", mEmDescent);
|
|
+ printf("%i\n", mMaxAscent);
|
|
+ printf("%i\n", mMaxDescent);
|
|
+ printf("%i\n", mMaxAdvance);
|
|
+ printf("%i\n", mSpaceWidth);
|
|
+ printf("%i\n", mAveCharWidth);
|
|
+#endif /* DEBUG_foo */
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -530,6 +550,10 @@
|
|
f = mDeviceContext->DevUnitsToAppUnits();
|
|
aWidth = NSToCoordRound(glyphInfo.xOff * f);
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("GetWidth (char *) %d\n", aWidth);
|
|
+#endif
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -553,6 +577,10 @@
|
|
if (aFontID)
|
|
*aFontID = 0;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("GetWidth %d\n", aWidth);
|
|
+#endif
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -586,6 +614,11 @@
|
|
if (nsnull != aFontID)
|
|
*aFontID = 0;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("GetTextDimensions %d %d %d\n", aDimensions.width,
|
|
+ aDimensions.ascent, aDimensions.descent);
|
|
+#endif
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -645,6 +678,10 @@
|
|
nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
|
|
data.drawBuffer = &drawBuffer;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("DrawString (char *)\n");
|
|
+#endif
|
|
+
|
|
return EnumerateGlyphs(aString, aLength,
|
|
&nsFontMetricsXft::DrawStringCallback, &data);
|
|
}
|
|
@@ -675,6 +712,10 @@
|
|
nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
|
|
data.drawBuffer = &drawBuffer;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("DrawString\n");
|
|
+#endif
|
|
+
|
|
return EnumerateGlyphs(aString, aLength,
|
|
&nsFontMetricsXft::DrawStringCallback, &data);
|
|
}
|
|
@@ -714,6 +755,15 @@
|
|
aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * P2T);
|
|
aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * P2T);
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("GetBoundingMetrics (char *)%d %d %d %d %d\n",
|
|
+ aBoundingMetrics.leftBearing,
|
|
+ aBoundingMetrics.rightBearing,
|
|
+ aBoundingMetrics.width,
|
|
+ aBoundingMetrics.ascent,
|
|
+ aBoundingMetrics.descent);
|
|
+#endif
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -755,6 +805,15 @@
|
|
if (nsnull != aFontID)
|
|
*aFontID = 0;
|
|
|
|
+#ifdef DEBUG_foo
|
|
+ printf("GetBoundingMetrics %d %d %d %d %d\n",
|
|
+ aBoundingMetrics.leftBearing,
|
|
+ aBoundingMetrics.rightBearing,
|
|
+ aBoundingMetrics.width,
|
|
+ aBoundingMetrics.ascent,
|
|
+ aBoundingMetrics.descent);
|
|
+#endif
|
|
+
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -766,6 +825,12 @@
|
|
return nsnull;
|
|
}
|
|
|
|
+nsresult
|
|
+nsFontMetricsXft::SetRightToLeftText(PRBool aIsRTL)
|
|
+{
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
PRUint32
|
|
nsFontMetricsXft::GetHints(void)
|
|
{
|
|
--- mozilla/gfx/src/gtk/Makefile.in.foo 2003-11-10 07:24:51.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/Makefile.in 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -102,6 +102,12 @@
|
|
nsFontMetricsXft.cpp
|
|
endif
|
|
|
|
+ifdef MOZ_ENABLE_PANGO
|
|
+CPPSRCS += \
|
|
+ nsFontMetricsPango.cpp \
|
|
+ mozilla-decoder.cpp
|
|
+endif
|
|
+
|
|
ifdef MOZ_ENABLE_GTK
|
|
CPPSRCS += \
|
|
nsRegionGTK.cpp \
|
|
@@ -155,10 +161,10 @@
|
|
endif
|
|
|
|
ifdef MOZ_ENABLE_XFT
|
|
-libs:: fontEncoding.properties
|
|
+libs:: fontEncoding.properties pangoFontEncoding.properties
|
|
$(INSTALL) $^ $(DIST)/bin/res/fonts
|
|
|
|
-install:: fontEncoding.properties
|
|
+install:: fontEncoding.properties pangoFontEncoding.properties
|
|
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res/fonts
|
|
endif
|
|
|
|
--- mozilla/gfx/src/gtk/pangoFontEncoding.properties.foo 2004-11-22 12:56:21.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/pangoFontEncoding.properties 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -0,0 +1,120 @@
|
|
+# ***** BEGIN LICENSE BLOCK *****
|
|
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
+#
|
|
+# The contents of this file are subject to the Mozilla Public License Version
|
|
+# 1.1 (the "License"); you may not use this file except in compliance with
|
|
+# the License. You may obtain a copy of the License at
|
|
+# http://www.mozilla.org/MPL/
|
|
+#
|
|
+# Software distributed under the License is distributed on an "AS IS" basis,
|
|
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
+# for the specific language governing rights and limitations under the
|
|
+# License.
|
|
+#
|
|
+# The Original Code is Mozilla MathML Project.
|
|
+#
|
|
+# The Initial Developer of the Original Code is
|
|
+# The University of Queensland.
|
|
+# Portions created by the Initial Developer are Copyright (C) 2001
|
|
+# the Initial Developer. All Rights Reserved.
|
|
+#
|
|
+# Contributor(s):
|
|
+# Roger B. Sidje <rbs@maths.uq.edu.au>
|
|
+# Jungshik Shin <jshin@mailaps.org>
|
|
+# Christopher Blizzard <blizzard@mozilla.org>
|
|
+#
|
|
+# Alternatively, the contents of this file may be used under the terms of
|
|
+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
+# in which case the provisions of the GPL or the LGPL are applicable instead
|
|
+# of those above. If you wish to allow use of your version of this file only
|
|
+# under the terms of either the GPL or the LGPL, and not to allow others to
|
|
+# use your version of this file under the terms of the MPL, indicate your
|
|
+# decision by deleting the provisions above and replace them with the notice
|
|
+# and other provisions required by the GPL or the LGPL. If you do not delete
|
|
+# the provisions above, a recipient may use your version of this file under
|
|
+# the terms of any one of the MPL, the GPL or the LGPL.
|
|
+#
|
|
+# ***** END LICENSE BLOCK *****
|
|
+
|
|
+# LOCALIZATION NOTE: FILE
|
|
+# Do not translate anything in this file
|
|
+
|
|
+# This file contains supported custom encodings for pango font
|
|
+# rendering. For information about the specific encodings, look at
|
|
+# fontEncoding.properties. It contains a lot more verbiage than you
|
|
+# will find here. There are a lot of encodings supported in the old
|
|
+# encoding file that pango supports directly, so there should be
|
|
+# little reason to use those custom encodings. The pango custom code
|
|
+# doesn't support .wide fonts, so consider yourself warned!
|
|
+#
|
|
+
|
|
+# To be honest, we basically support mathml and that's about it.
|
|
+
|
|
+encoding.cmr10.ttf = x-ttf-cmr
|
|
+encoding.cmmi10.ttf = x-ttf-cmmi
|
|
+encoding.cmsy10.ttf = x-ttf-cmsy
|
|
+encoding.cmex10.ttf = x-ttf-cmex
|
|
+
|
|
+encoding.cmr10.ftcmap = unicode
|
|
+encoding.cmmi10.ftcmap = unicode
|
|
+encoding.cmsy10.ftcmap = unicode
|
|
+encoding.cmex10.ftcmap = unicode
|
|
+
|
|
+encoding.math1.ttf = x-mathematica1
|
|
+encoding.math1-bold.ttf = x-mathematica1
|
|
+encoding.math1mono.ttf = x-mathematica1
|
|
+encoding.math1mono-bold.ttf = x-mathematica1
|
|
+
|
|
+encoding.math2.ttf = x-mathematica2
|
|
+encoding.math2-bold.ttf = x-mathematica2
|
|
+encoding.math2mono.ttf = x-mathematica2
|
|
+encoding.math2mono-bold.ttf = x-mathematica2
|
|
+
|
|
+encoding.math3.ttf = x-mathematica3
|
|
+encoding.math3-bold.ttf = x-mathematica3
|
|
+encoding.math3mono.ttf = x-mathematica3
|
|
+encoding.math3mono-bold.ttf = x-mathematica3
|
|
+
|
|
+encoding.math4.ttf = x-mathematica4
|
|
+encoding.math4-bold.ttf = x-mathematica4
|
|
+encoding.math4mono.ttf = x-mathematica4
|
|
+encoding.math4mono-bold.ttf = x-mathematica4
|
|
+
|
|
+encoding.math5.ttf = x-mathematica5
|
|
+encoding.math5-bold.ttf = x-mathematica5
|
|
+encoding.math5bold.ttf = x-mathematica5
|
|
+encoding.math5mono.ttf = x-mathematica5
|
|
+encoding.math5mono-bold.ttf = x-mathematica5
|
|
+encoding.math5monobold.ttf = x-mathematica5
|
|
+
|
|
+encoding.math1.ftcmap = mac_roman
|
|
+encoding.math1-bold.ftcmap = mac_roman
|
|
+encoding.math1mono.ftcmap = mac_roman
|
|
+encoding.math1mono-bold.ftcmap = mac_roman
|
|
+
|
|
+encoding.math2.ftcmap = mac_roman
|
|
+encoding.math2-bold.ftcmap = mac_roman
|
|
+encoding.math2mono.ftcmap = mac_roman
|
|
+encoding.math2mono-bold.ftcmap = mac_roman
|
|
+
|
|
+encoding.math3.ftcmap = mac_roman
|
|
+encoding.math3-bold.ftcmap = mac_roman
|
|
+encoding.math3mono.ftcmap = mac_roman
|
|
+encoding.math3mono-bold.ftcmap = mac_roman
|
|
+
|
|
+encoding.math4.ftcmap = mac_roman
|
|
+encoding.math4-bold.ftcmap = mac_roman
|
|
+encoding.math4mono.ftcmap = mac_roman
|
|
+encoding.math4mono-bold.ftcmap = mac_roman
|
|
+
|
|
+encoding.math5.ftcmap = mac_roman
|
|
+encoding.math5-bold.ftcmap = mac_roman
|
|
+encoding.math5bold.ftcmap = mac_roman
|
|
+encoding.math5mono.ftcmap = mac_roman
|
|
+encoding.math5mono-bold.ftcmap = mac_roman
|
|
+encoding.math5monobold.ftcmap = mac_roman
|
|
+
|
|
+encoding.mtextra.ttf = x-mtextra
|
|
+encoding.mtextra.ftcmap = mac_roman
|
|
+
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp.foo 2002-10-11 22:03:32.000000000 -0400
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp 2004-11-22 12:57:33.000000000 -0500
|
|
@@ -50,11 +50,20 @@
|
|
#include "nsFontMetricsGTK.h"
|
|
#endif
|
|
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+#include "nsFontMetricsPango.h"
|
|
+#endif
|
|
+
|
|
#include "nsFontMetricsUtils.h"
|
|
|
|
PRUint32
|
|
NS_FontMetricsGetHints(void)
|
|
{
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ if (NS_IsPangoEnabled()) {
|
|
+ return nsFontMetricsPango::GetHints();
|
|
+ }
|
|
+#endif
|
|
#ifdef MOZ_ENABLE_XFT
|
|
if (NS_IsXftEnabled()) {
|
|
return nsFontMetricsXft::GetHints();
|
|
@@ -69,6 +78,11 @@
|
|
nsresult
|
|
NS_FontMetricsFamilyExists(nsIDeviceContext *aDevice, const nsString &aName)
|
|
{
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+ if (NS_IsPangoEnabled()) {
|
|
+ return nsFontMetricsPango::FamilyExists(aDevice, aName);
|
|
+ }
|
|
+#endif
|
|
#ifdef MOZ_ENABLE_XFT
|
|
// try to fall through to the core fonts if xft fails
|
|
if (NS_IsXftEnabled()) {
|
|
@@ -121,3 +135,17 @@
|
|
}
|
|
|
|
#endif /* MOZ_ENABLE_XFT */
|
|
+
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+
|
|
+PRBool
|
|
+NS_IsPangoEnabled(void)
|
|
+{
|
|
+ char *val = PR_GetEnv("MOZ_DISABLE_PANGO");
|
|
+ if (val)
|
|
+ return FALSE;
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+#endif
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsPango.cpp.foo 2004-11-22 12:56:21.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -0,0 +1,1662 @@
|
|
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
+/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
+ */
|
|
+/* ***** BEGIN LICENSE BLOCK *****
|
|
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
+ *
|
|
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
+ * the License. You may obtain a copy of the License at
|
|
+ * http://www.mozilla.org/MPL/
|
|
+ *
|
|
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
+ * for the specific language governing rights and limitations under the
|
|
+ * License.
|
|
+ *
|
|
+ * The Original Code is mozilla.org code.
|
|
+ *
|
|
+ * The Initial Developer of the Original Code is Christopher Blizzard
|
|
+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
|
|
+ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
|
+ *
|
|
+ * Contributor(s):
|
|
+ *
|
|
+ * Alternatively, the contents of this file may be used under the terms of
|
|
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
+ * of those above. If you wish to allow use of your version of this file only
|
|
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
+ * use your version of this file under the terms of the MPL, indicate your
|
|
+ * decision by deleting the provisions above and replace them with the notice
|
|
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
+ * the provisions above, a recipient may use your version of this file under
|
|
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
+ *
|
|
+ * ***** END LICENSE BLOCK ***** */
|
|
+
|
|
+#include "nsFont.h"
|
|
+#include "nsIDeviceContext.h"
|
|
+#include "nsICharsetConverterManager.h"
|
|
+#include "nsIPref.h"
|
|
+#include "nsIServiceManagerUtils.h"
|
|
+
|
|
+#define PANGO_ENABLE_BACKEND
|
|
+#define PANGO_ENABLE_ENGINE
|
|
+
|
|
+#include "nsFontMetricsPango.h"
|
|
+#include "nsRenderingContextGTK.h"
|
|
+#include "nsDeviceContextGTK.h"
|
|
+
|
|
+#include "nsUnicharUtils.h"
|
|
+#include "nsQuickSort.h"
|
|
+
|
|
+#include <pango/pangoxft.h>
|
|
+#include <fontconfig/fontconfig.h>
|
|
+#include <gdk/gdk.h>
|
|
+#include <gdk/gdkx.h>
|
|
+#include <freetype/tttables.h>
|
|
+
|
|
+#include "mozilla-decoder.h"
|
|
+
|
|
+#define FORCE_PR_LOG
|
|
+#include "prlog.h"
|
|
+
|
|
+// Globals
|
|
+
|
|
+static PRLogModuleInfo *gPangoFontLog;
|
|
+static int gNumInstances;
|
|
+
|
|
+// Defines
|
|
+
|
|
+// This is the scaling factor that we keep fonts limited to against
|
|
+// the display size. If a pixel size is requested that is more than
|
|
+// this factor larger than the height of the display, it's clamped to
|
|
+// that value instead of the requested size.
|
|
+#define FONT_MAX_FONT_SCALE 2
|
|
+
|
|
+static NS_DEFINE_CID(kCharsetConverterManagerCID,
|
|
+ NS_ICHARSETCONVERTERMANAGER_CID);
|
|
+
|
|
+struct MozPangoLangGroup {
|
|
+ const char *mozLangGroup;
|
|
+ const char *PangoLang;
|
|
+};
|
|
+
|
|
+static const MozPangoLangGroup MozPangoLangGroups[] = {
|
|
+ { "x-western", "en" },
|
|
+ { "x-central-euro", "pl" },
|
|
+ { "x-cyrillic", "ru" },
|
|
+ { "x-baltic", "lv" },
|
|
+ { "x-devanagari", "hi" },
|
|
+ { "x-tamil", "ta" },
|
|
+ { "x-unicode", 0 },
|
|
+ { "x-user-def", 0 },
|
|
+};
|
|
+
|
|
+#define NUM_PANGO_LANG_GROUPS (sizeof (MozPangoLangGroups) / \
|
|
+ sizeof (MozPangoLangGroups[0]))
|
|
+
|
|
+#ifdef DEBUG
|
|
+#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \
|
|
+ printf("0x%x ", ustr[llen]); \
|
|
+ printf("\n");
|
|
+#endif
|
|
+
|
|
+// rounding and truncation functions for a Freetype floating point number
|
|
+// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
|
|
+// part and low 6 bits for the fractional part.
|
|
+#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
|
|
+#define MOZ_FT_TRUNC(x) ((x) >> 6)
|
|
+#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
|
|
+ MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
|
|
+
|
|
+// Static function decls
|
|
+
|
|
+static PRBool IsASCIIFontName (const nsString& aName);
|
|
+static int FFRECountHyphens (nsACString &aFFREName);
|
|
+
|
|
+static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup);
|
|
+static const MozPangoLangGroup* FindPangoLangGroup (nsACString &aLangGroup);
|
|
+
|
|
+static void FreeGlobals (void);
|
|
+
|
|
+static PangoStyle CalculateStyle (PRUint8 aStyle);
|
|
+static PangoWeight CalculateWeight (PRUint16 aWeight);
|
|
+
|
|
+static nsresult EnumFontsPango (nsIAtom* aLangGroup, const char* aGeneric,
|
|
+ PRUint32* aCount, PRUnichar*** aResult);
|
|
+static int CompareFontNames (const void* aArg1, const void* aArg2,
|
|
+ void* aClosure);
|
|
+
|
|
+extern void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
|
|
+
|
|
+nsFontMetricsPango::nsFontMetricsPango()
|
|
+{
|
|
+ if (!gPangoFontLog)
|
|
+ gPangoFontLog = PR_NewLogModule("PangoFont");
|
|
+
|
|
+ gNumInstances++;
|
|
+
|
|
+ mPangoFontDesc = nsnull;
|
|
+ mPangoContext = nsnull;
|
|
+ mLTRPangoContext = nsnull;
|
|
+ mRTLPangoContext = nsnull;
|
|
+ mPangoAttrList = nsnull;
|
|
+ mIsRTL = PR_FALSE;
|
|
+
|
|
+ static PRBool initialized = PR_FALSE;
|
|
+ if (initialized)
|
|
+ return;
|
|
+
|
|
+ // Initialized the custom decoders
|
|
+ if (!mozilla_decoders_init())
|
|
+ initialized = PR_TRUE;
|
|
+}
|
|
+
|
|
+nsFontMetricsPango::~nsFontMetricsPango()
|
|
+{
|
|
+ delete mFont;
|
|
+
|
|
+ if (mDeviceContext)
|
|
+ mDeviceContext->FontMetricsDeleted(this);
|
|
+
|
|
+ if (mPangoFontDesc)
|
|
+ pango_font_description_free(mPangoFontDesc);
|
|
+
|
|
+ if (mLTRPangoContext)
|
|
+ g_object_unref(mLTRPangoContext);
|
|
+
|
|
+ if (mRTLPangoContext)
|
|
+ g_object_unref(mRTLPangoContext);
|
|
+
|
|
+ if (mPangoAttrList)
|
|
+ pango_attr_list_unref(mPangoAttrList);
|
|
+
|
|
+ // XXX clean up all the pango objects
|
|
+
|
|
+ if (--gNumInstances == 0)
|
|
+ FreeGlobals();
|
|
+}
|
|
+
|
|
+
|
|
+NS_IMPL_ISUPPORTS1(nsFontMetricsPango, nsIFontMetrics)
|
|
+
|
|
+// nsIFontMetrics impl
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontMetricsPango::Init(const nsFont& aFont, nsIAtom* aLangGroup,
|
|
+ nsIDeviceContext *aContext)
|
|
+{
|
|
+ mFont = new nsFont(aFont);
|
|
+ mLangGroup = aLangGroup;
|
|
+
|
|
+ // Hang on to the device context
|
|
+ mDeviceContext = aContext;
|
|
+
|
|
+ mPointSize = NSTwipsToFloatPoints(mFont->size);
|
|
+
|
|
+ // Make sure to clamp the pixel size to something reasonable so we
|
|
+ // don't make the X server blow up.
|
|
+ nscoord screenPixels = gdk_screen_height();
|
|
+ mPointSize = PR_MIN(screenPixels * FONT_MAX_FONT_SCALE, mPointSize);
|
|
+
|
|
+ // enumerate over the font names passed in
|
|
+ mFont->EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
|
|
+
|
|
+ nsCOMPtr<nsIPref> prefService;
|
|
+ prefService = do_GetService(NS_PREF_CONTRACTID);
|
|
+ if (!prefService)
|
|
+ return NS_ERROR_FAILURE;
|
|
+
|
|
+ nsXPIDLCString value;
|
|
+
|
|
+ // Set up the default font name if it's not set
|
|
+ if (!mGenericFont) {
|
|
+ prefService->CopyCharPref("font.default", getter_Copies(value));
|
|
+
|
|
+ if (value.get())
|
|
+ mDefaultFont = value.get();
|
|
+ else
|
|
+ mDefaultFont = "serif";
|
|
+
|
|
+ mGenericFont = &mDefaultFont;
|
|
+ }
|
|
+
|
|
+ // set up the minimum sizes for fonts
|
|
+ if (mLangGroup) {
|
|
+ nsCAutoString name("font.min-size.");
|
|
+
|
|
+ if (mGenericFont->Equals("monospace"))
|
|
+ name.Append("fixed");
|
|
+ else
|
|
+ name.Append("variable");
|
|
+
|
|
+ name.Append(char('.'));
|
|
+
|
|
+ const char* langGroup;
|
|
+ mLangGroup->GetUTF8String(&langGroup);
|
|
+
|
|
+ name.Append(langGroup);
|
|
+
|
|
+ PRInt32 minimumInt = 0;
|
|
+ float minimum;
|
|
+ nsresult res;
|
|
+ res = prefService->GetIntPref(name.get(), &minimumInt);
|
|
+ if (NS_FAILED(res))
|
|
+ prefService->GetDefaultIntPref(name.get(), &minimumInt);
|
|
+
|
|
+ if (minimumInt < 0)
|
|
+ minimumInt = 0;
|
|
+
|
|
+ minimum = minimumInt;
|
|
+
|
|
+ // The minimum size is specified in pixels, not in points.
|
|
+ // Convert the size from pixels to points.
|
|
+ minimum = NSTwipsToFloatPoints(NSFloatPixelsToTwips(minimum, mDeviceContext->DevUnitsToAppUnits()));
|
|
+ if (mPointSize < minimum)
|
|
+ mPointSize = minimum;
|
|
+ }
|
|
+
|
|
+ // Make sure that the pixel size is at least greater than zero
|
|
+ if (mPointSize < 1) {
|
|
+#ifdef DEBUG
|
|
+ printf("*** Warning: nsFontMetricsPango created with point size %f\n",
|
|
+ mPointSize);
|
|
+#endif
|
|
+ mPointSize = 1;
|
|
+ }
|
|
+
|
|
+ nsresult rv = RealizeFont();
|
|
+ if (NS_FAILED(rv))
|
|
+ return rv;
|
|
+
|
|
+ // Cache font metrics for the 'x' character
|
|
+ return CacheFontMetrics();
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::CacheFontMetrics(void)
|
|
+{
|
|
+ // Get our scale factor
|
|
+ float f;
|
|
+ float val;
|
|
+ f = mDeviceContext->DevUnitsToAppUnits();
|
|
+
|
|
+ mPangoAttrList = pango_attr_list_new();
|
|
+
|
|
+ GList *items = pango_itemize(mPangoContext,
|
|
+ "a", 0, 1, mPangoAttrList, NULL);
|
|
+
|
|
+ if (!items)
|
|
+ return NS_ERROR_FAILURE;
|
|
+
|
|
+ guint nitems = g_list_length(items);
|
|
+ if (nitems != 1)
|
|
+ return NS_ERROR_FAILURE;
|
|
+
|
|
+ PangoItem *item = (PangoItem *)items->data;
|
|
+ PangoFcFont *fcfont = PANGO_FC_FONT(item->analysis.font);
|
|
+ if (!fcfont)
|
|
+ return NS_ERROR_FAILURE;
|
|
+
|
|
+ // Get our font face
|
|
+ FT_Face face;
|
|
+ TT_OS2 *os2;
|
|
+ XftFont *xftFont = pango_xft_font_get_font(PANGO_FONT(fcfont));
|
|
+ if (!xftFont)
|
|
+ return NS_ERROR_NOT_AVAILABLE;
|
|
+
|
|
+ face = XftLockFace(xftFont);
|
|
+ os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
|
|
+
|
|
+ // mEmHeight (size in pixels of EM height)
|
|
+ int size;
|
|
+ if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) !=
|
|
+ FcResultMatch) {
|
|
+ size = 12;
|
|
+ }
|
|
+ mEmHeight = PR_MAX(1, nscoord(size * f));
|
|
+
|
|
+ // mMaxAscent
|
|
+ mMaxAscent = nscoord(xftFont->ascent * f);
|
|
+
|
|
+ // mMaxDescent
|
|
+ mMaxDescent = nscoord(xftFont->descent * f);
|
|
+
|
|
+ nscoord lineHeight = mMaxAscent + mMaxDescent;
|
|
+
|
|
+ // mLeading (needs ascent and descent and EM height)
|
|
+ if (lineHeight > mEmHeight)
|
|
+ mLeading = lineHeight - mEmHeight;
|
|
+ else
|
|
+ mLeading = 0;
|
|
+
|
|
+ // mMaxHeight (needs ascent and descent)
|
|
+ mMaxHeight = lineHeight;
|
|
+
|
|
+ // mEmAscent (needs maxascent, EM height, ascent and descent)
|
|
+ mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight);
|
|
+
|
|
+ // mEmDescent (needs EM height and EM ascent
|
|
+ mEmDescent = mEmHeight - mEmAscent;
|
|
+
|
|
+ // mMaxAdvance
|
|
+ mMaxAdvance = nscoord(xftFont->max_advance_width * f);
|
|
+
|
|
+ // mSpaceWidth (width of a space)
|
|
+ nscoord tmpWidth;
|
|
+ GetWidth(" ", 1, tmpWidth, NULL);
|
|
+ mSpaceWidth = tmpWidth;
|
|
+
|
|
+ // mAveCharWidth (width of an 'average' char)
|
|
+ // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
|
|
+ //rawWidth = extents.width;
|
|
+ //mAveCharWidth = NSToCoordRound(rawWidth * f);
|
|
+ GetWidth("x", 1, tmpWidth, NULL);
|
|
+ mAveCharWidth = tmpWidth;
|
|
+
|
|
+ // mXHeight (height of an 'x' character)
|
|
+ PRUnichar xUnichar('x');
|
|
+ XGlyphInfo extents;
|
|
+ if (FcCharSetHasChar(xftFont->charset, xUnichar)) {
|
|
+ XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
|
|
+ mXHeight = extents.height;
|
|
+ }
|
|
+ else {
|
|
+ // 56% of ascent, best guess for non-true type or asian fonts
|
|
+ mXHeight = nscoord(((float)mMaxAscent) * 0.56);
|
|
+ }
|
|
+ mXHeight = nscoord(mXHeight * f);
|
|
+
|
|
+ // mUnderlineOffset (offset for underlines)
|
|
+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position,
|
|
+ face->size->metrics.y_scale);
|
|
+ if (val) {
|
|
+ mUnderlineOffset = NSToIntRound(val * f);
|
|
+ }
|
|
+ else {
|
|
+ mUnderlineOffset =
|
|
+ -NSToIntRound(PR_MAX(1, floor(0.1 * xftFont->height + 0.5)) * f);
|
|
+ }
|
|
+
|
|
+ // mUnderlineSize (thickness of an underline)
|
|
+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness,
|
|
+ face->size->metrics.y_scale);
|
|
+ if (val) {
|
|
+ mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f)));
|
|
+ }
|
|
+ else {
|
|
+ mUnderlineSize =
|
|
+ NSToIntRound(PR_MAX(1, floor(0.05 * xftFont->height + 0.5)) * f);
|
|
+ }
|
|
+
|
|
+ // mSuperscriptOffset
|
|
+ if (os2 && os2->ySuperscriptYOffset) {
|
|
+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySuperscriptYOffset,
|
|
+ face->size->metrics.y_scale);
|
|
+ mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
|
|
+ }
|
|
+ else {
|
|
+ mSuperscriptOffset = mXHeight;
|
|
+ }
|
|
+
|
|
+ // mSubscriptOffset
|
|
+ if (os2 && os2->ySubscriptYOffset) {
|
|
+ val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySubscriptYOffset,
|
|
+ face->size->metrics.y_scale);
|
|
+ // some fonts have the incorrect sign.
|
|
+ val = (val < 0) ? -val : val;
|
|
+ mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
|
|
+ }
|
|
+ else {
|
|
+ mSubscriptOffset = mXHeight;
|
|
+ }
|
|
+
|
|
+ // mStrikeoutOffset
|
|
+ mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
|
|
+
|
|
+ // mStrikeoutSize
|
|
+ mStrikeoutSize = mUnderlineSize;
|
|
+
|
|
+ XftUnlockFace(xftFont);
|
|
+
|
|
+ /*
|
|
+ printf("%i\n", mXHeight);
|
|
+ printf("%i\n", mSuperscriptOffset);
|
|
+ printf("%i\n", mSubscriptOffset);
|
|
+ printf("%i\n", mStrikeoutOffset);
|
|
+ printf("%i\n", mStrikeoutSize);
|
|
+ printf("%i\n", mUnderlineOffset);
|
|
+ printf("%i\n", mUnderlineSize);
|
|
+ printf("%i\n", mMaxHeight);
|
|
+ printf("%i\n", mLeading);
|
|
+ printf("%i\n", mEmHeight);
|
|
+ printf("%i\n", mEmAscent);
|
|
+ printf("%i\n", mEmDescent);
|
|
+ printf("%i\n", mMaxAscent);
|
|
+ printf("%i\n", mMaxDescent);
|
|
+ printf("%i\n", mMaxAdvance);
|
|
+ printf("%i\n", mSpaceWidth);
|
|
+ printf("%i\n", mAveCharWidth);
|
|
+ */
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontMetricsPango::Destroy()
|
|
+{
|
|
+ mDeviceContext = nsnull;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontMetricsPango::GetFont(const nsFont *&aFont)
|
|
+{
|
|
+ aFont = mFont;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontMetricsPango::GetLangGroup(nsIAtom** aLangGroup)
|
|
+{
|
|
+ *aLangGroup = mLangGroup;
|
|
+ NS_IF_ADDREF(*aLangGroup);
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontMetricsPango::GetFontHandle(nsFontHandle &aHandle)
|
|
+{
|
|
+ return NS_ERROR_NOT_IMPLEMENTED;
|
|
+}
|
|
+
|
|
+// nsIFontMetricsPango impl
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
|
|
+ nscoord& aWidth,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ pango_layout_set_text(layout, aString, aLength);
|
|
+
|
|
+ int width, height;
|
|
+
|
|
+ pango_layout_get_size(layout, &width, &height);
|
|
+
|
|
+ width /= PANGO_SCALE;
|
|
+
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ float f;
|
|
+ f = mDeviceContext->DevUnitsToAppUnits();
|
|
+ aWidth = NSToCoordRound(width * f);
|
|
+
|
|
+ // printf("GetWidth (char *) %d\n", aWidth);
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
|
|
+ nscoord& aWidth, PRInt32 *aFontID,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ nsresult rv = NS_OK;
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ gchar *text = g_utf16_to_utf8(aString, aLength,
|
|
+ NULL, NULL, NULL);
|
|
+
|
|
+ if (!text) {
|
|
+ aWidth = 0;
|
|
+#ifdef DEBUG
|
|
+ NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
|
|
+ DUMP_PRUNICHAR(aString, aLength)
|
|
+#endif
|
|
+ rv = NS_ERROR_FAILURE;
|
|
+ goto loser;
|
|
+ }
|
|
+
|
|
+ gint width, height;
|
|
+
|
|
+ pango_layout_set_text(layout, text, strlen(text));
|
|
+ pango_layout_get_size(layout, &width, &height);
|
|
+
|
|
+ width /= PANGO_SCALE;
|
|
+
|
|
+ float f;
|
|
+ f = mDeviceContext->DevUnitsToAppUnits();
|
|
+ aWidth = NSToCoordRound(width * f);
|
|
+
|
|
+ // printf("GetWidth %d\n", aWidth);
|
|
+
|
|
+ loser:
|
|
+ g_free(text);
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
|
|
+ PRUint32 aLength,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ nsresult rv = NS_OK;
|
|
+
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ gchar *text = g_utf16_to_utf8(aString, aLength,
|
|
+ NULL, NULL, NULL);
|
|
+
|
|
+ if (!text) {
|
|
+#ifdef DEBUG
|
|
+ NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
|
|
+ DUMP_PRUNICHAR(aString, aLength)
|
|
+#endif
|
|
+ aDimensions.width = 0;
|
|
+ aDimensions.ascent = 0;
|
|
+ aDimensions.descent = 0;
|
|
+
|
|
+ rv = NS_ERROR_FAILURE;
|
|
+ goto loser;
|
|
+ }
|
|
+
|
|
+
|
|
+ pango_layout_set_text(layout, text, strlen(text));
|
|
+
|
|
+ // Get the logical extents
|
|
+ PangoLayoutLine *line;
|
|
+ if (pango_layout_get_line_count(layout) != 1) {
|
|
+ printf("Warning: more than one line!\n");
|
|
+ }
|
|
+ line = pango_layout_get_line(layout, 0);
|
|
+
|
|
+ PangoRectangle rect;
|
|
+ pango_layout_line_get_extents(line, NULL, &rect);
|
|
+
|
|
+ float P2T;
|
|
+ P2T = mDeviceContext->DevUnitsToAppUnits();
|
|
+
|
|
+ aDimensions.width = NSToCoordRound(rect.width / PANGO_SCALE * P2T);
|
|
+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) / PANGO_SCALE * P2T);
|
|
+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) / PANGO_SCALE * P2T);
|
|
+
|
|
+ // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
|
|
+ //aDimensions.ascent, aDimensions.descent);
|
|
+
|
|
+ loser:
|
|
+ g_free(text);
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetTextDimensions(const char* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+
|
|
+ return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
|
|
+ aNumBreaks, aDimensions, aNumCharsFit,
|
|
+ aLastWordDimensions, aContext);
|
|
+
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ nsresult rv = NS_OK;
|
|
+ PRInt32 curBreak = 0;
|
|
+ gchar *curChar;
|
|
+
|
|
+ PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
|
|
+
|
|
+ gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
|
|
+ NULL, NULL, NULL);
|
|
+
|
|
+ curChar = text;
|
|
+
|
|
+ if (!text) {
|
|
+#ifdef DEBUG
|
|
+ NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
|
|
+ DUMP_PRUNICHAR(aString, (PRUint32)aLength)
|
|
+#endif
|
|
+ rv = NS_ERROR_FAILURE;
|
|
+ goto loser;
|
|
+ }
|
|
+
|
|
+ // Covert the utf16 break offsets to utf8 break offsets
|
|
+ for (PRInt32 curOffset=0; curOffset < aLength;
|
|
+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
|
|
+ if (aBreaks[curBreak] == curOffset) {
|
|
+ utf8Breaks[curBreak] = curChar - text;
|
|
+ curBreak++;
|
|
+ }
|
|
+
|
|
+ if (IS_HIGH_SURROGATE(aString[curOffset]))
|
|
+ curOffset++;
|
|
+ }
|
|
+
|
|
+ // Always catch the last break
|
|
+ utf8Breaks[curBreak] = curChar - text;
|
|
+
|
|
+#if 0
|
|
+ if (strlen(text) != aLength) {
|
|
+ printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
|
|
+ DUMP_PRUNICHAR(aString, aLength)
|
|
+ DUMP_PRUNICHAR(text, strlen(text))
|
|
+ for (PRInt32 i = 0; i < aNumBreaks; ++i) {
|
|
+ printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ // We'll use curBreak to indicate which of the breaks end up being
|
|
+ // used for the break point for this line.
|
|
+ curBreak = 0;
|
|
+ rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
|
|
+ aNumBreaks, aDimensions, aNumCharsFit,
|
|
+ aLastWordDimensions, aContext);
|
|
+
|
|
+ // Figure out which of the breaks we ended up using to convert
|
|
+ // back to utf16 - start from the end.
|
|
+ for (PRInt32 i = aNumBreaks - 1; i >= 0; --i) {
|
|
+ if (utf8Breaks[i] == aNumCharsFit) {
|
|
+ // if (aNumCharsFit != aBreaks[i])
|
|
+ // printf("Fixing utf8 -> utf16 %d -> %d\n", aNumCharsFit, aBreaks[i]);
|
|
+ aNumCharsFit = aBreaks[i];
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ loser:
|
|
+ if (text)
|
|
+ g_free(text);
|
|
+
|
|
+ delete[] utf8Breaks;
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
|
|
+ nscoord aX, nscoord aY,
|
|
+ const nscoord* aSpacing,
|
|
+ nsRenderingContextGTK *aContext,
|
|
+ nsDrawingSurfaceGTK *aSurface)
|
|
+{
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ pango_layout_set_text(layout, aString, aLength);
|
|
+
|
|
+ int x = aX;
|
|
+ int y = aY;
|
|
+
|
|
+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
|
|
+
|
|
+ PangoLayoutLine *line;
|
|
+ if (pango_layout_get_line_count(layout) != 1) {
|
|
+ printf("Warning: more than one line!\n");
|
|
+ }
|
|
+ line = pango_layout_get_line(layout, 0);
|
|
+
|
|
+ aContext->UpdateGC();
|
|
+ GdkGC *gc = aContext->GetGC();
|
|
+
|
|
+ if (aSpacing && *aSpacing) {
|
|
+ DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
|
|
+ gc, x, y, line, aSpacing);
|
|
+ }
|
|
+ else {
|
|
+ gdk_draw_layout_line(aSurface->GetDrawable(), gc,
|
|
+ x, y,
|
|
+ line);
|
|
+ }
|
|
+
|
|
+ g_object_unref(gc);
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ // printf("DrawString (char *)\n");
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
|
|
+ nscoord aX, nscoord aY,
|
|
+ PRInt32 aFontID,
|
|
+ const nscoord* aSpacing,
|
|
+ nsRenderingContextGTK *aContext,
|
|
+ nsDrawingSurfaceGTK *aSurface)
|
|
+{
|
|
+ nsresult rv = NS_OK;
|
|
+ int x = aX;
|
|
+ int y = aY;
|
|
+
|
|
+ aContext->UpdateGC();
|
|
+ GdkGC *gc = aContext->GetGC();
|
|
+
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ gchar *text = g_utf16_to_utf8(aString, aLength,
|
|
+ NULL, NULL, NULL);
|
|
+
|
|
+ if (!text) {
|
|
+#ifdef DEBUG
|
|
+ NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
|
|
+ DUMP_PRUNICHAR(aString, aLength)
|
|
+#endif
|
|
+ rv = NS_ERROR_FAILURE;
|
|
+ goto loser;
|
|
+ }
|
|
+
|
|
+ pango_layout_set_text(layout, text, strlen(text));
|
|
+
|
|
+ aContext->GetTranMatrix()->TransformCoord(&x, &y);
|
|
+
|
|
+ PangoLayoutLine *line;
|
|
+ if (pango_layout_get_line_count(layout) != 1) {
|
|
+ printf("Warning: more than one line!\n");
|
|
+ }
|
|
+ line = pango_layout_get_line(layout, 0);
|
|
+
|
|
+ if (aSpacing && *aSpacing) {
|
|
+ DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
|
|
+ gc, x, y, line, aSpacing);
|
|
+ }
|
|
+ else {
|
|
+ gdk_draw_layout_line(aSurface->GetDrawable(), gc,
|
|
+ x, y,
|
|
+ line);
|
|
+ }
|
|
+
|
|
+ loser:
|
|
+
|
|
+ g_free(text);
|
|
+ g_object_unref(gc);
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ // printf("DrawString\n");
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+#ifdef MOZ_MATHML
|
|
+nsresult
|
|
+nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
|
|
+ nsBoundingMetrics &aBoundingMetrics,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ printf("GetBoundingMetrics (char *)\n");
|
|
+ return NS_ERROR_FAILURE;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
|
|
+ PRUint32 aLength,
|
|
+ nsBoundingMetrics &aBoundingMetrics,
|
|
+ PRInt32 *aFontID,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ nsresult rv = NS_OK;
|
|
+ PangoLayout *layout = pango_layout_new(mPangoContext);
|
|
+
|
|
+ gchar *text = g_utf16_to_utf8(aString, aLength,
|
|
+ NULL, NULL, NULL);
|
|
+
|
|
+ if (!text) {
|
|
+#ifdef DEBUG
|
|
+ NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
|
|
+ DUMP_PRUNICHAR(aString, aLength)
|
|
+#endif
|
|
+ aBoundingMetrics.leftBearing = 0;
|
|
+ aBoundingMetrics.rightBearing = 0;
|
|
+ aBoundingMetrics.width = 0;
|
|
+ aBoundingMetrics.ascent = 0;
|
|
+ aBoundingMetrics.descent = 0;
|
|
+
|
|
+ rv = NS_ERROR_FAILURE;
|
|
+ goto loser;
|
|
+ }
|
|
+
|
|
+ pango_layout_set_text(layout, text, strlen(text));
|
|
+
|
|
+ // Get the logical extents
|
|
+ PangoLayoutLine *line;
|
|
+ if (pango_layout_get_line_count(layout) != 1) {
|
|
+ printf("Warning: more than one line!\n");
|
|
+ }
|
|
+ line = pango_layout_get_line(layout, 0);
|
|
+
|
|
+ // Get the ink extents
|
|
+ PangoRectangle rect;
|
|
+ pango_layout_line_get_extents(line, NULL, &rect);
|
|
+
|
|
+ float P2T;
|
|
+ P2T = mDeviceContext->DevUnitsToAppUnits();
|
|
+
|
|
+ aBoundingMetrics.leftBearing =
|
|
+ NSToCoordRound(rect.x / PANGO_SCALE * P2T);
|
|
+ aBoundingMetrics.rightBearing =
|
|
+ NSToCoordRound(rect.width / PANGO_SCALE * P2T);
|
|
+ aBoundingMetrics.width = NSToCoordRound((rect.x + rect.width) / PANGO_SCALE * P2T);
|
|
+ aBoundingMetrics.ascent = NSToCoordRound(rect.y / PANGO_SCALE * P2T);
|
|
+ aBoundingMetrics.descent = NSToCoordRound(rect.height / PANGO_SCALE * P2T);
|
|
+
|
|
+ loser:
|
|
+ g_free(text);
|
|
+ g_object_unref(layout);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+#endif /* MOZ_MATHML */
|
|
+
|
|
+GdkFont*
|
|
+nsFontMetricsPango::GetCurrentGDKFont(void)
|
|
+{
|
|
+ return nsnull;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
|
|
+{
|
|
+ if (aIsRTL) {
|
|
+ if (!mRTLPangoContext) {
|
|
+ mRTLPangoContext = pango_xft_get_context(GDK_DISPLAY(), 0);
|
|
+ pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
|
|
+
|
|
+ gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
|
|
+ pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
|
|
+ pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
|
|
+ }
|
|
+ mPangoContext = mRTLPangoContext;
|
|
+ }
|
|
+ else {
|
|
+ mPangoContext = mLTRPangoContext;
|
|
+ }
|
|
+
|
|
+ mIsRTL = aIsRTL;
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PRUint32
|
|
+nsFontMetricsPango::GetHints(void)
|
|
+{
|
|
+ return (NS_RENDERING_HINT_BIDI_REORDERING |
|
|
+ NS_RENDERING_HINT_ARABIC_SHAPING |
|
|
+ NS_RENDERING_HINT_FAST_MEASURE);
|
|
+}
|
|
+
|
|
+/* static */
|
|
+nsresult
|
|
+nsFontMetricsPango::FamilyExists(nsIDeviceContext *aDevice,
|
|
+ const nsString &aName)
|
|
+{
|
|
+ if (!IsASCIIFontName(aName))
|
|
+ return NS_ERROR_FAILURE;
|
|
+
|
|
+ NS_ConvertUCS2toUTF8 name(aName);
|
|
+
|
|
+ nsresult rv = NS_ERROR_FAILURE;
|
|
+ PangoContext *context = pango_xft_get_context(GDK_DISPLAY(), 0);
|
|
+ PangoFontFamily **familyList;
|
|
+ int n;
|
|
+
|
|
+ pango_context_list_families(context, &familyList, &n);
|
|
+
|
|
+ for (int i=0; i < n; i++) {
|
|
+ const char *tmpname = pango_font_family_get_name(familyList[i]);
|
|
+ if (!Compare(nsDependentCString(tmpname), name,
|
|
+ nsCaseInsensitiveCStringComparator())) {
|
|
+ rv = NS_OK;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_free(familyList);
|
|
+ g_object_unref(context);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+// Private Methods
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::RealizeFont(void)
|
|
+{
|
|
+ nsCString familyList;
|
|
+ // Create and fill out the font description.
|
|
+ mPangoFontDesc = pango_font_description_new();
|
|
+
|
|
+ // Add CSS names - walk the list of fonts, adding the generic as
|
|
+ // the last font
|
|
+ for (int i=0; i < mFontList.Count(); ++i) {
|
|
+ // if this was a generic name, break out of the loop since we
|
|
+ // don't want to add it to the pattern yet
|
|
+ if (mFontIsGeneric[i])
|
|
+ break;;
|
|
+
|
|
+ nsCString *familyName = mFontList.CStringAt(i);
|
|
+ familyList.Append(familyName->get());
|
|
+ familyList.Append(',');
|
|
+ }
|
|
+
|
|
+ // If there's a generic add a pref for the generic if there's one
|
|
+ // set.
|
|
+ if (mGenericFont && !mFont->systemFont) {
|
|
+ nsCString name;
|
|
+ name += "font.name.";
|
|
+ name += mGenericFont->get();
|
|
+ name += ".";
|
|
+
|
|
+ nsString langGroup;
|
|
+ mLangGroup->ToString(langGroup);
|
|
+
|
|
+ name.AppendWithConversion(langGroup);
|
|
+
|
|
+ nsCOMPtr<nsIPref> pref;
|
|
+ pref = do_GetService(NS_PREF_CONTRACTID);
|
|
+ if (pref) {
|
|
+ nsresult rv;
|
|
+ nsXPIDLCString value;
|
|
+ rv = pref->GetCharPref(name.get(), getter_Copies(value));
|
|
+
|
|
+ // we ignore prefs that have three hypens since they are X
|
|
+ // style prefs.
|
|
+ if (FFRECountHyphens(value) < 3) {
|
|
+ nsCString tmpstr;
|
|
+ tmpstr.Append(value);
|
|
+
|
|
+ familyList.Append(tmpstr);
|
|
+ familyList.Append(',');
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Add the generic if there is one.
|
|
+ if (mGenericFont && !mFont->systemFont) {
|
|
+ familyList.Append(mGenericFont->get());
|
|
+ familyList.Append(',');
|
|
+ }
|
|
+
|
|
+ // Set the family
|
|
+ pango_font_description_set_family(mPangoFontDesc,
|
|
+ familyList.get());
|
|
+
|
|
+ // Set the point size
|
|
+ pango_font_description_set_size(mPangoFontDesc,
|
|
+ (gint)(mPointSize * PANGO_SCALE));
|
|
+
|
|
+ // Set the style
|
|
+ pango_font_description_set_style(mPangoFontDesc,
|
|
+ CalculateStyle(mFont->style));
|
|
+
|
|
+ // Set the weight
|
|
+ pango_font_description_set_weight(mPangoFontDesc,
|
|
+ CalculateWeight(mFont->weight));
|
|
+
|
|
+ // Now that we have the font description set up, create the
|
|
+ // context.
|
|
+ mLTRPangoContext = pango_xft_get_context(GDK_DISPLAY(), 0);
|
|
+ mPangoContext = mLTRPangoContext;
|
|
+
|
|
+ // Set the color map so we can draw later.
|
|
+ gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
|
|
+
|
|
+ // Set the pango language now that we have a context
|
|
+ pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
|
|
+
|
|
+ // And attach the font description to this context
|
|
+ pango_context_set_font_description(mPangoContext, mPangoFontDesc);
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PRBool
|
|
+nsFontMetricsPango::EnumFontCallback(const nsString &aFamily,
|
|
+ PRBool aIsGeneric, void *aData)
|
|
+{
|
|
+ // make sure it's an ascii name, if not then return and continue
|
|
+ // enumerating
|
|
+ if (!IsASCIIFontName(aFamily))
|
|
+ return PR_TRUE;
|
|
+
|
|
+ nsCAutoString name;
|
|
+ name.AssignWithConversion(aFamily.get());
|
|
+ ToLowerCase(name);
|
|
+ nsFontMetricsPango *metrics = (nsFontMetricsPango *)aData;
|
|
+ metrics->mFontList.AppendCString(name);
|
|
+ metrics->mFontIsGeneric.AppendElement((void *)aIsGeneric);
|
|
+ if (aIsGeneric) {
|
|
+ metrics->mGenericFont =
|
|
+ metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1);
|
|
+ return PR_FALSE; // stop processing
|
|
+ }
|
|
+
|
|
+ return PR_TRUE; // keep processing
|
|
+}
|
|
+
|
|
+/*
|
|
+ * This is only used when there's per-character spacing happening.
|
|
+ * Well, really it can be either line or character spacing but it's
|
|
+ * just turtles all the way down!
|
|
+ */
|
|
+
|
|
+void
|
|
+nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
|
|
+ const PRUnichar *aOrigString,
|
|
+ PRUint32 aLength,
|
|
+ GdkDrawable *aDrawable,
|
|
+ GdkGC *aGC, gint aX, gint aY,
|
|
+ PangoLayoutLine *aLine,
|
|
+ const nscoord *aSpacing)
|
|
+{
|
|
+ float app2dev;
|
|
+ app2dev = mDeviceContext->AppUnitsToDevUnits();
|
|
+ gint offset = 0;
|
|
+
|
|
+ /*
|
|
+ * We walk the list of glyphs returned in each layout run,
|
|
+ * matching up the glyphs with the characters in the source text.
|
|
+ * We use the aSpacing argument to figure out where to place those
|
|
+ * glyphs. It's important to note that since the string we're
|
|
+ * working with is in UTF-8 while the spacing argument assumes
|
|
+ * that offset will be part of the UTF-16 string. Logical
|
|
+ * attributes in pango are in byte offsets in the UTF-8 string, so
|
|
+ * we need to store the offsets based on the UTF-8 string.
|
|
+ */
|
|
+ nscoord *utf8spacing = new nscoord[strlen(aText)];
|
|
+
|
|
+ if (aOrigString) {
|
|
+ const gchar *curChar = aText;
|
|
+ bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
|
|
+
|
|
+ // Covert the utf16 spacing offsets to utf8 spacing offsets
|
|
+ for (PRUint32 curOffset=0; curOffset < aLength;
|
|
+ curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
|
|
+ utf8spacing[curChar - aText] = aSpacing[curOffset];
|
|
+
|
|
+ if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
|
|
+ curOffset++;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
|
|
+ }
|
|
+
|
|
+ gint curRun = 0;
|
|
+
|
|
+ for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
|
|
+ tmpList = tmpList->next, curRun++) {
|
|
+ PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
|
|
+ gint tmpOffset = 0;
|
|
+
|
|
+ /* printf(" Rendering run %d: \"%s\"\n", curRun,
|
|
+ &aText[layoutRun->item->offset]); */
|
|
+
|
|
+ for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
|
|
+ /* printf("glyph %d offset %d orig width %d new width %d\n", i,
|
|
+ * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
|
|
+ * layoutRun->glyphs->glyphs[i].geometry.width,
|
|
+ * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
|
|
+ */
|
|
+ gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
|
|
+ * app2dev * PANGO_SCALE);
|
|
+ layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
|
|
+ tmpOffset += thisOffset;
|
|
+ }
|
|
+
|
|
+ /* printf(" rendering at X coord %d\n", aX + offset); */
|
|
+
|
|
+ gdk_draw_glyphs(aDrawable, aGC, layoutRun->item->analysis.font,
|
|
+ aX + (gint)(offset / PANGO_SCALE), aY, layoutRun->glyphs);
|
|
+
|
|
+ offset += tmpOffset;
|
|
+ }
|
|
+
|
|
+ delete[] utf8spacing;
|
|
+}
|
|
+
|
|
+nsresult
|
|
+nsFontMetricsPango::GetTextDimensionsInternal(const gchar* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ nsRenderingContextGTK *aContext)
|
|
+{
|
|
+ NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
|
|
+
|
|
+ // If we need to back up this state represents the last place
|
|
+ // we could break. We can use this to avoid remeasuring text
|
|
+ PRInt32 prevBreakState_BreakIndex = -1; // not known
|
|
+ // (hasn't been computed)
|
|
+ nscoord prevBreakState_Width = 0; // accumulated width to this point
|
|
+
|
|
+ // Initialize OUT parameters
|
|
+ GetMaxAscent(aLastWordDimensions.ascent);
|
|
+ GetMaxDescent(aLastWordDimensions.descent);
|
|
+ aLastWordDimensions.width = -1;
|
|
+ aNumCharsFit = 0;
|
|
+
|
|
+ // Iterate each character in the string and determine which font to use
|
|
+ nscoord width = 0;
|
|
+ PRInt32 start = 0;
|
|
+ nscoord aveCharWidth;
|
|
+ GetAveCharWidth(aveCharWidth);
|
|
+
|
|
+ while (start < aLength) {
|
|
+ // Estimate how many characters will fit. Do that by
|
|
+ // diving the available space by the average character
|
|
+ // width. Make sure the estimated number of characters is
|
|
+ // at least 1
|
|
+ PRInt32 estimatedNumChars = 0;
|
|
+
|
|
+ if (aveCharWidth > 0)
|
|
+ estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
|
|
+
|
|
+ if (estimatedNumChars < 1)
|
|
+ estimatedNumChars = 1;
|
|
+
|
|
+ // Find the nearest break offset
|
|
+ PRInt32 estimatedBreakOffset = start + estimatedNumChars;
|
|
+ PRInt32 breakIndex;
|
|
+ nscoord numChars;
|
|
+
|
|
+ // Find the nearest place to break that is less than or equal to
|
|
+ // the estimated break offset
|
|
+ if (aLength <= estimatedBreakOffset) {
|
|
+ // All the characters should fit
|
|
+ numChars = aLength - start;
|
|
+ breakIndex = aNumBreaks - 1;
|
|
+ }
|
|
+ else {
|
|
+ breakIndex = prevBreakState_BreakIndex;
|
|
+ while (((breakIndex + 1) < aNumBreaks) &&
|
|
+ (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
|
|
+ ++breakIndex;
|
|
+ }
|
|
+
|
|
+ if (breakIndex == prevBreakState_BreakIndex) {
|
|
+ ++breakIndex; // make sure we advanced past the
|
|
+ // previous break index
|
|
+ }
|
|
+
|
|
+ numChars = aBreaks[breakIndex] - start;
|
|
+ }
|
|
+
|
|
+ // Measure the text
|
|
+ nscoord twWidth = 0;
|
|
+ if ((1 == numChars) && (aString[start] == ' '))
|
|
+ GetSpaceWidth(twWidth);
|
|
+ else if (numChars > 0)
|
|
+ GetWidth(&aString[start], numChars, twWidth, aContext);
|
|
+
|
|
+ // See if the text fits
|
|
+ PRBool textFits = (twWidth + width) <= aAvailWidth;
|
|
+
|
|
+ // If the text fits then update the width and the number of
|
|
+ // characters that fit
|
|
+ if (textFits) {
|
|
+ aNumCharsFit += numChars;
|
|
+ width += twWidth;
|
|
+ start += numChars;
|
|
+
|
|
+ // This is a good spot to back up to if we need to so remember
|
|
+ // this state
|
|
+ prevBreakState_BreakIndex = breakIndex;
|
|
+ prevBreakState_Width = width;
|
|
+ }
|
|
+ else {
|
|
+ // See if we can just back up to the previous saved
|
|
+ // state and not have to measure any text
|
|
+ if (prevBreakState_BreakIndex > 0) {
|
|
+ // If the previous break index is just before the
|
|
+ // current break index then we can use it
|
|
+ if (prevBreakState_BreakIndex == (breakIndex - 1)) {
|
|
+ aNumCharsFit = aBreaks[prevBreakState_BreakIndex];
|
|
+ width = prevBreakState_Width;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // We can't just revert to the previous break state
|
|
+ if (0 == breakIndex) {
|
|
+ // There's no place to back up to, so even though
|
|
+ // the text doesn't fit return it anyway
|
|
+ aNumCharsFit += numChars;
|
|
+ width += twWidth;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // Repeatedly back up until we get to where the text
|
|
+ // fits or we're all the way back to the first word
|
|
+ width += twWidth;
|
|
+ while ((breakIndex >= 1) && (width > aAvailWidth)) {
|
|
+ twWidth = 0;
|
|
+ start = aBreaks[breakIndex - 1];
|
|
+ numChars = aBreaks[breakIndex] - start;
|
|
+
|
|
+ if ((1 == numChars) && (aString[start] == ' '))
|
|
+ GetSpaceWidth(twWidth);
|
|
+ else if (numChars > 0)
|
|
+ GetWidth(&aString[start], numChars, twWidth,
|
|
+ aContext);
|
|
+ width -= twWidth;
|
|
+ aNumCharsFit = start;
|
|
+ breakIndex--;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ aDimensions.width = width;
|
|
+ GetMaxAscent(aDimensions.ascent);
|
|
+ GetMaxDescent(aDimensions.descent);
|
|
+
|
|
+ /* printf("aDimensions %d %d %d aLastWordDimensions %d %d %d aNumCharsFit %d\n",
|
|
+ aDimensions.width, aDimensions.ascent, aDimensions.descent,
|
|
+ aLastWordDimensions.width, aLastWordDimensions.ascent, aLastWordDimensions.descent,
|
|
+ aNumCharsFit); */
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PRBool
|
|
+IsASCIIFontName(const nsString& aName)
|
|
+{
|
|
+ PRUint32 len = aName.Length();
|
|
+ const PRUnichar* str = aName.get();
|
|
+ for (PRUint32 i = 0; i < len; i++) {
|
|
+ /*
|
|
+ * X font names are printable ASCII, ignore others (for now)
|
|
+ */
|
|
+ if ((str[i] < 0x20) || (str[i] > 0x7E)) {
|
|
+ return PR_FALSE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return PR_TRUE;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+int
|
|
+FFRECountHyphens (nsACString &aFFREName)
|
|
+{
|
|
+ int h = 0;
|
|
+ PRInt32 hyphen = 0;
|
|
+ while ((hyphen = aFFREName.FindChar('-', hyphen)) >= 0) {
|
|
+ ++h;
|
|
+ ++hyphen;
|
|
+ }
|
|
+ return h;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PangoLanguage *
|
|
+GetPangoLanguage(nsIAtom *aLangGroup)
|
|
+{
|
|
+ // Find the FC lang group for this lang group
|
|
+ nsCAutoString cname;
|
|
+ aLangGroup->ToUTF8String(cname);
|
|
+
|
|
+ // see if the lang group needs to be translated from mozilla's
|
|
+ // internal mapping into fontconfig's
|
|
+ const struct MozPangoLangGroup *langGroup;
|
|
+ langGroup = FindPangoLangGroup(cname);
|
|
+
|
|
+ // if there's no lang group, just use the lang group as it was
|
|
+ // passed to us
|
|
+ //
|
|
+ // we're casting away the const here for the strings - should be
|
|
+ // safe.
|
|
+ if (!langGroup)
|
|
+ return pango_language_from_string(cname.get());
|
|
+ else if (langGroup->PangoLang)
|
|
+ return pango_language_from_string(langGroup->PangoLang);
|
|
+
|
|
+ return pango_language_from_string("en");
|
|
+}
|
|
+
|
|
+/* static */
|
|
+const MozPangoLangGroup*
|
|
+FindPangoLangGroup (nsACString &aLangGroup)
|
|
+{
|
|
+ for (unsigned int i=0; i < NUM_PANGO_LANG_GROUPS; ++i) {
|
|
+ if (aLangGroup.Equals(MozPangoLangGroups[i].mozLangGroup,
|
|
+ nsCaseInsensitiveCStringComparator())) {
|
|
+ return &MozPangoLangGroups[i];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return nsnull;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+void
|
|
+FreeGlobals(void)
|
|
+{
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PangoStyle
|
|
+CalculateStyle(PRUint8 aStyle)
|
|
+{
|
|
+ switch(aStyle) {
|
|
+ case NS_FONT_STYLE_ITALIC:
|
|
+ return PANGO_STYLE_OBLIQUE;
|
|
+ break;
|
|
+ case NS_FONT_STYLE_OBLIQUE:
|
|
+ return PANGO_STYLE_OBLIQUE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return PANGO_STYLE_NORMAL;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+PangoWeight
|
|
+CalculateWeight (PRUint16 aWeight)
|
|
+{
|
|
+ /*
|
|
+ * weights come in two parts crammed into one
|
|
+ * integer -- the "base" weight is weight / 100,
|
|
+ * the rest of the value is the "offset" from that
|
|
+ * weight -- the number of steps to move to adjust
|
|
+ * the weight in the list of supported font weights,
|
|
+ * this value can be negative or positive.
|
|
+ */
|
|
+ PRInt32 baseWeight = (aWeight + 50) / 100;
|
|
+ PRInt32 offset = aWeight - baseWeight * 100;
|
|
+
|
|
+ /* clip weights to range 0 to 9 */
|
|
+ if (baseWeight < 0)
|
|
+ baseWeight = 0;
|
|
+ if (baseWeight > 9)
|
|
+ baseWeight = 9;
|
|
+
|
|
+ /* Map from weight value to fcWeights index */
|
|
+ static int fcWeightLookup[10] = {
|
|
+ 0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
|
|
+ };
|
|
+
|
|
+ PRInt32 fcWeight = fcWeightLookup[baseWeight];
|
|
+
|
|
+ /*
|
|
+ * adjust by the offset value, make sure we stay inside the
|
|
+ * fcWeights table
|
|
+ */
|
|
+ fcWeight += offset;
|
|
+
|
|
+ if (fcWeight < 0)
|
|
+ fcWeight = 0;
|
|
+ if (fcWeight > 4)
|
|
+ fcWeight = 4;
|
|
+
|
|
+ /* Map to final PANGO_WEIGHT value */
|
|
+ static int fcWeights[5] = {
|
|
+ 349,
|
|
+ 499,
|
|
+ 649,
|
|
+ 749,
|
|
+ 999
|
|
+ };
|
|
+
|
|
+ return (PangoWeight)fcWeights[fcWeight];
|
|
+}
|
|
+
|
|
+/* static */
|
|
+nsresult
|
|
+EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric,
|
|
+ PRUint32* aCount, PRUnichar*** aResult)
|
|
+{
|
|
+ FcPattern *pat = NULL;
|
|
+ FcObjectSet *os = NULL;
|
|
+ FcFontSet *fs = NULL;
|
|
+ nsresult rv = NS_ERROR_FAILURE;
|
|
+
|
|
+ PRUnichar **array = NULL;
|
|
+ PRUint32 narray = 0;
|
|
+ PRInt32 serif = 0, sansSerif = 0, monospace = 0, nGenerics;
|
|
+
|
|
+ *aCount = 0;
|
|
+ *aResult = nsnull;
|
|
+
|
|
+ pat = FcPatternCreate();
|
|
+ if (!pat)
|
|
+ goto end;
|
|
+
|
|
+ os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, 0);
|
|
+ if (!os)
|
|
+ goto end;
|
|
+
|
|
+ // take the pattern and add the lang group to it
|
|
+ if (aLangGroup)
|
|
+ AddLangGroup(pat, aLangGroup);
|
|
+
|
|
+ // get the font list
|
|
+ fs = FcFontList(0, pat, os);
|
|
+
|
|
+ if (!fs)
|
|
+ goto end;
|
|
+
|
|
+ if (!fs->nfont) {
|
|
+ rv = NS_OK;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
|
|
+ // "monospace", slightly different from CSS's 5.
|
|
+ if (!aGeneric)
|
|
+ serif = sansSerif = monospace = 1;
|
|
+ else if (!strcmp(aGeneric, "serif"))
|
|
+ serif = 1;
|
|
+ else if (!strcmp(aGeneric, "sans-serif"))
|
|
+ sansSerif = 1;
|
|
+ else if (!strcmp(aGeneric, "monospace"))
|
|
+ monospace = 1;
|
|
+ else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
|
|
+ serif = sansSerif = 1;
|
|
+ else
|
|
+ NS_NOTREACHED("unexpected generic family");
|
|
+ nGenerics = serif + sansSerif + monospace;
|
|
+
|
|
+ array = NS_STATIC_CAST(PRUnichar **,
|
|
+ nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
|
|
+ if (!array)
|
|
+ goto end;
|
|
+
|
|
+ if (serif) {
|
|
+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
|
|
+ if (!name)
|
|
+ goto end;
|
|
+ array[narray++] = name;
|
|
+ }
|
|
+
|
|
+ if (sansSerif) {
|
|
+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
|
|
+ if (!name)
|
|
+ goto end;
|
|
+ array[narray++] = name;
|
|
+ }
|
|
+
|
|
+ if (monospace) {
|
|
+ PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
|
|
+ if (!name)
|
|
+ goto end;
|
|
+ array[narray++] = name;
|
|
+ }
|
|
+
|
|
+ for (int i=0; i < fs->nfont; ++i) {
|
|
+ char *family;
|
|
+ PRUnichar *name;
|
|
+
|
|
+ // if there's no family, just move to the next iteration
|
|
+ if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
|
|
+ (FcChar8 **) &family) != FcResultMatch) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ name = NS_STATIC_CAST(PRUnichar *,
|
|
+ nsMemory::Alloc ((strlen (family) + 1)
|
|
+ * sizeof (PRUnichar)));
|
|
+
|
|
+ if (!name)
|
|
+ goto end;
|
|
+
|
|
+ PRUnichar *r = name;
|
|
+ for (char *f = family; *f; ++f)
|
|
+ *r++ = *f;
|
|
+ *r = '\0';
|
|
+
|
|
+ array[narray++] = name;
|
|
+ }
|
|
+
|
|
+ NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
|
|
+ CompareFontNames, nsnull);
|
|
+
|
|
+ *aCount = narray;
|
|
+ if (narray)
|
|
+ *aResult = array;
|
|
+ else
|
|
+ nsMemory::Free(array);
|
|
+
|
|
+ rv = NS_OK;
|
|
+
|
|
+ end:
|
|
+ if (NS_FAILED(rv) && array) {
|
|
+ while (narray)
|
|
+ nsMemory::Free (array[--narray]);
|
|
+ nsMemory::Free (array);
|
|
+ }
|
|
+ if (pat)
|
|
+ FcPatternDestroy(pat);
|
|
+ if (os)
|
|
+ FcObjectSetDestroy(os);
|
|
+ if (fs)
|
|
+ FcFontSetDestroy(fs);
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+/* static */
|
|
+int
|
|
+CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure)
|
|
+{
|
|
+ const PRUnichar* str1 = *((const PRUnichar**) aArg1);
|
|
+ const PRUnichar* str2 = *((const PRUnichar**) aArg2);
|
|
+
|
|
+ return nsCRT::strcmp(str1, str2);
|
|
+}
|
|
+
|
|
+
|
|
+// nsFontEnumeratorPango class
|
|
+
|
|
+nsFontEnumeratorPango::nsFontEnumeratorPango()
|
|
+{
|
|
+}
|
|
+
|
|
+NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator)
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount,
|
|
+ PRUnichar ***aResult)
|
|
+{
|
|
+ NS_ENSURE_ARG_POINTER(aResult);
|
|
+ *aResult = nsnull;
|
|
+ NS_ENSURE_ARG_POINTER(aCount);
|
|
+ *aCount = 0;
|
|
+
|
|
+ return EnumFontsPango(nsnull, nsnull, aCount, aResult);
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup,
|
|
+ const char *aGeneric,
|
|
+ PRUint32 *aCount,
|
|
+ PRUnichar ***aResult)
|
|
+{
|
|
+ NS_ENSURE_ARG_POINTER(aResult);
|
|
+ *aResult = nsnull;
|
|
+ NS_ENSURE_ARG_POINTER(aCount);
|
|
+ *aCount = 0;
|
|
+
|
|
+ // aLangGroup=null or "" means any (i.e., don't care)
|
|
+ // aGeneric=null or "" means any (i.e, don't care)
|
|
+ nsCOMPtr<nsIAtom> langGroup;
|
|
+ if (aLangGroup && *aLangGroup)
|
|
+ langGroup = do_GetAtom(aLangGroup);
|
|
+ const char* generic = nsnull;
|
|
+ if (aGeneric && *aGeneric)
|
|
+ generic = aGeneric;
|
|
+
|
|
+ return EnumFontsPango(langGroup, generic, aCount, aResult);
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup,
|
|
+ PRBool *aResult)
|
|
+{
|
|
+ NS_ENSURE_ARG_POINTER(aResult);
|
|
+ *aResult = PR_FALSE;
|
|
+ NS_ENSURE_ARG_POINTER(aLangGroup);
|
|
+
|
|
+ *aResult = PR_TRUE; // always return true for now.
|
|
+ // Finish me - ftang
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup,
|
|
+ const char *aGeneric,
|
|
+ PRUnichar **aResult)
|
|
+{
|
|
+ NS_ENSURE_ARG_POINTER(aResult);
|
|
+ *aResult = nsnull;
|
|
+
|
|
+ // Have a look at nsFontEnumeratorXft::GetDefaultFont for some
|
|
+ // possible code for this function.
|
|
+
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
+NS_IMETHODIMP
|
|
+nsFontEnumeratorPango::UpdateFontList(PRBool *_retval)
|
|
+{
|
|
+ *_retval = PR_FALSE; // always return false for now
|
|
+ return NS_OK;
|
|
+}
|
|
--- mozilla/gfx/src/gtk/nsRenderingContextGTK.h.foo 2003-02-24 21:38:34.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsRenderingContextGTK.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -194,6 +194,8 @@
|
|
const nsRect &aDestBounds, PRUint32 aCopyFlags);
|
|
NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd);
|
|
|
|
+ NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
|
|
+
|
|
NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint);
|
|
NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect);
|
|
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsPango.h.foo 2004-11-22 12:56:21.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsPango.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -0,0 +1,278 @@
|
|
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
+/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
+ */
|
|
+/* ***** BEGIN LICENSE BLOCK *****
|
|
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
+ *
|
|
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
+ * the License. You may obtain a copy of the License at
|
|
+ * http://www.mozilla.org/MPL/
|
|
+ *
|
|
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
+ * for the specific language governing rights and limitations under the
|
|
+ * License.
|
|
+ *
|
|
+ * The Original Code is mozilla.org code.
|
|
+ *
|
|
+ * The Initial Developer of the Original Code Christopher Blizzard
|
|
+ * <blizzard@mozilla.org>. Portions created by the Initial Developer
|
|
+ * are Copyright (C) 2002 the Initial Developer. All Rights Reserved.
|
|
+ *
|
|
+ * Contributor(s):
|
|
+ *
|
|
+ * Alternatively, the contents of this file may be used under the terms of
|
|
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
+ * of those above. If you wish to allow use of your version of this file only
|
|
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
+ * use your version of this file under the terms of the MPL, indicate your
|
|
+ * decision by deleting the provisions above and replace them with the notice
|
|
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
+ * the provisions above, a recipient may use your version of this file under
|
|
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
+ *
|
|
+ * ***** END LICENSE BLOCK ***** */
|
|
+
|
|
+#include "nsIFontMetrics.h"
|
|
+#include "nsIFontEnumerator.h"
|
|
+#include "nsCRT.h"
|
|
+#include "nsIAtom.h"
|
|
+#include "nsString.h"
|
|
+#include "nsVoidArray.h"
|
|
+#include "nsIFontMetricsGTK.h"
|
|
+
|
|
+#include <pango/pango.h>
|
|
+
|
|
+class nsFontMetricsPango : public nsIFontMetricsGTK
|
|
+{
|
|
+public:
|
|
+ nsFontMetricsPango();
|
|
+ virtual ~nsFontMetricsPango();
|
|
+
|
|
+ NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
|
+
|
|
+ // nsISupports
|
|
+ NS_DECL_ISUPPORTS
|
|
+
|
|
+ // nsIFontMetrics
|
|
+ NS_IMETHOD Init (const nsFont& aFont, nsIAtom* aLangGroup,
|
|
+ nsIDeviceContext *aContext);
|
|
+ NS_IMETHOD Destroy();
|
|
+ NS_IMETHOD GetFont (const nsFont *&aFont);
|
|
+ NS_IMETHOD GetLangGroup (nsIAtom** aLangGroup);
|
|
+ NS_IMETHOD GetFontHandle (nsFontHandle &aHandle);
|
|
+
|
|
+ NS_IMETHOD GetXHeight (nscoord& aResult)
|
|
+ { aResult = mXHeight; return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetSuperscriptOffset (nscoord& aResult)
|
|
+ { aResult = mSuperscriptOffset;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetSubscriptOffset (nscoord& aResult)
|
|
+ { aResult = mSubscriptOffset;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetStrikeout (nscoord& aOffset, nscoord& aSize)
|
|
+ { aOffset = mStrikeoutOffset;
|
|
+ aSize = mStrikeoutSize;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetUnderline (nscoord& aOffset, nscoord& aSize)
|
|
+ { aOffset = mUnderlineOffset;
|
|
+ aSize = mUnderlineSize;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetHeight (nscoord &aHeight)
|
|
+ { aHeight = mMaxHeight;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetNormalLineHeight (nscoord &aHeight)
|
|
+ { aHeight = mEmHeight + mLeading;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetLeading (nscoord &aLeading)
|
|
+ { aLeading = mLeading;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetEmHeight (nscoord &aHeight)
|
|
+ { aHeight = mEmHeight;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetEmAscent (nscoord &aAscent)
|
|
+ { aAscent = mEmAscent;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetEmDescent (nscoord &aDescent)
|
|
+ { aDescent = mEmDescent;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetMaxHeight (nscoord &aHeight)
|
|
+ { aHeight = mMaxHeight;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetMaxAscent (nscoord &aAscent)
|
|
+ { aAscent = mMaxAscent;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetMaxDescent (nscoord &aDescent)
|
|
+ { aDescent = mMaxDescent;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetMaxAdvance (nscoord &aAdvance)
|
|
+ { aAdvance = mMaxAdvance;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetSpaceWidth (nscoord &aSpaceCharWidth)
|
|
+ { aSpaceCharWidth = mSpaceWidth;
|
|
+ return NS_OK; };
|
|
+
|
|
+ NS_IMETHOD GetAveCharWidth (nscoord &aAveCharWidth)
|
|
+ { aAveCharWidth = mAveCharWidth;
|
|
+ return NS_OK; };
|
|
+
|
|
+ // nsIFontMetricsGTK (calls from the font rendering layer)
|
|
+ virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
|
|
+ nscoord& aWidth,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+ virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
|
|
+ nscoord& aWidth, PRInt32 *aFontID,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+
|
|
+ virtual nsresult GetTextDimensions(const PRUnichar* aString,
|
|
+ PRUint32 aLength,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+ virtual nsresult GetTextDimensions(const char* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+ virtual nsresult GetTextDimensions(const PRUnichar* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ PRInt32* aFontID,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+
|
|
+ virtual nsresult DrawString(const char *aString, PRUint32 aLength,
|
|
+ nscoord aX, nscoord aY,
|
|
+ const nscoord* aSpacing,
|
|
+ nsRenderingContextGTK *aContext,
|
|
+ nsDrawingSurfaceGTK *aSurface);
|
|
+ virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
|
|
+ nscoord aX, nscoord aY,
|
|
+ PRInt32 aFontID,
|
|
+ const nscoord* aSpacing,
|
|
+ nsRenderingContextGTK *aContext,
|
|
+ nsDrawingSurfaceGTK *aSurface);
|
|
+
|
|
+#ifdef MOZ_MATHML
|
|
+ virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
|
|
+ nsBoundingMetrics &aBoundingMetrics,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+ virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
|
|
+ PRUint32 aLength,
|
|
+ nsBoundingMetrics &aBoundingMetrics,
|
|
+ PRInt32 *aFontID,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+#endif /* MOZ_MATHML */
|
|
+
|
|
+ virtual GdkFont* GetCurrentGDKFont(void);
|
|
+
|
|
+ virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
|
+
|
|
+ // get hints for the font
|
|
+ static PRUint32 GetHints (void);
|
|
+
|
|
+ // drawing surface methods
|
|
+ static nsresult FamilyExists (nsIDeviceContext *aDevice,
|
|
+ const nsString &aName);
|
|
+
|
|
+private:
|
|
+
|
|
+ // generic font metrics class bits
|
|
+ nsCStringArray mFontList;
|
|
+ nsAutoVoidArray mFontIsGeneric;
|
|
+
|
|
+ nsIDeviceContext *mDeviceContext;
|
|
+ nsCOMPtr<nsIAtom> mLangGroup;
|
|
+ nsCString *mGenericFont;
|
|
+ nsFont *mFont;
|
|
+ float mPointSize;
|
|
+
|
|
+ nsCAutoString mDefaultFont;
|
|
+
|
|
+ // Pango-related items
|
|
+ PangoFontDescription *mPangoFontDesc;
|
|
+ PangoContext *mPangoContext;
|
|
+ PangoContext *mLTRPangoContext;
|
|
+ PangoContext *mRTLPangoContext;
|
|
+ PangoAttrList *mPangoAttrList;
|
|
+ PRBool mIsRTL;
|
|
+
|
|
+ // Cached font metrics
|
|
+ nscoord mXHeight;
|
|
+ nscoord mSuperscriptOffset;
|
|
+ nscoord mSubscriptOffset;
|
|
+ nscoord mStrikeoutOffset;
|
|
+ nscoord mStrikeoutSize;
|
|
+ nscoord mUnderlineOffset;
|
|
+ nscoord mUnderlineSize;
|
|
+ nscoord mMaxHeight;
|
|
+ nscoord mLeading;
|
|
+ nscoord mEmHeight;
|
|
+ nscoord mEmAscent;
|
|
+ nscoord mEmDescent;
|
|
+ nscoord mMaxAscent;
|
|
+ nscoord mMaxDescent;
|
|
+ nscoord mMaxAdvance;
|
|
+ nscoord mSpaceWidth;
|
|
+ nscoord mAveCharWidth;
|
|
+
|
|
+ // Private methods
|
|
+ nsresult RealizeFont(void);
|
|
+ nsresult CacheFontMetrics(void);
|
|
+
|
|
+ static PRBool EnumFontCallback(const nsString &aFamily,
|
|
+ PRBool aIsGeneric, void *aData);
|
|
+
|
|
+ void DrawStringSlowly(const gchar *aText,
|
|
+ const PRUnichar *aOrigString,
|
|
+ PRUint32 aLength,
|
|
+ GdkDrawable *aDrawable,
|
|
+ GdkGC *aGC, gint aX, gint aY,
|
|
+ PangoLayoutLine *aLine,
|
|
+ const nscoord *aSpacing);
|
|
+
|
|
+ nsresult GetTextDimensionsInternal(const gchar* aString,
|
|
+ PRInt32 aLength,
|
|
+ PRInt32 aAvailWidth,
|
|
+ PRInt32* aBreaks,
|
|
+ PRInt32 aNumBreaks,
|
|
+ nsTextDimensions& aDimensions,
|
|
+ PRInt32& aNumCharsFit,
|
|
+ nsTextDimensions& aLastWordDimensions,
|
|
+ nsRenderingContextGTK *aContext);
|
|
+};
|
|
+
|
|
+class nsFontEnumeratorPango : public nsIFontEnumerator
|
|
+{
|
|
+public:
|
|
+ nsFontEnumeratorPango();
|
|
+ NS_DECL_ISUPPORTS
|
|
+ NS_DECL_NSIFONTENUMERATOR
|
|
+};
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsUtils.h.foo 2002-10-11 22:03:32.000000000 -0400
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsUtils.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -42,9 +42,12 @@
|
|
extern PRUint32 NS_FontMetricsGetHints (void);
|
|
extern nsresult NS_FontMetricsFamilyExists(nsIDeviceContext *aDevice,
|
|
const nsString &aName);
|
|
-
|
|
#ifdef MOZ_ENABLE_XFT
|
|
extern PRBool NS_IsXftEnabled(void);
|
|
#endif
|
|
|
|
+#ifdef MOZ_ENABLE_PANGO
|
|
+extern PRBool NS_IsPangoEnabled(void);
|
|
+#endif
|
|
+
|
|
#endif /* __nsFontMetricsUtils_h */
|
|
--- mozilla/gfx/src/gtk/nsIFontMetricsGTK.h.foo 2002-10-11 23:00:17.000000000 -0400
|
|
+++ mozilla/gfx/src/gtk/nsIFontMetricsGTK.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -121,6 +121,9 @@
|
|
// particular handle.
|
|
virtual GdkFont* GetCurrentGDKFont(void) = 0;
|
|
|
|
+ // Set the direction of the text rendering
|
|
+ virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0;
|
|
+
|
|
};
|
|
|
|
#endif /* __nsIFontMetricsGTK_h */
|
|
--- mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp.foo 2004-02-12 11:52:22.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -524,6 +524,9 @@
|
|
|
|
values.foreground.pixel =
|
|
gdk_rgb_xpixel_from_rgb(NS_TO_GDK_RGB(mCurrentColor));
|
|
+ values.foreground.red = (NS_GET_R(mCurrentColor) << 8) | NS_GET_R(mCurrentColor);
|
|
+ values.foreground.green = (NS_GET_G(mCurrentColor) << 8) | NS_GET_G(mCurrentColor);
|
|
+ values.foreground.blue = (NS_GET_B(mCurrentColor) << 8) | NS_GET_B(mCurrentColor);
|
|
valuesMask = GDK_GC_FOREGROUND;
|
|
|
|
#ifdef MOZ_ENABLE_COREXFONTS
|
|
@@ -1438,6 +1441,11 @@
|
|
|
|
#endif /* MOZ_MATHML */
|
|
|
|
+NS_IMETHODIMP nsRenderingContextGTK::SetRightToLeftText(PRBool aIsRTL)
|
|
+{
|
|
+ return mFontMetrics->SetRightToLeftText(aIsRTL);
|
|
+}
|
|
+
|
|
NS_IMETHODIMP nsRenderingContextGTK::DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint)
|
|
{
|
|
UpdateGC();
|
|
--- mozilla/gfx/src/gtk/nsGCCache.cpp.foo 2002-02-02 22:47:15.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsGCCache.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -232,98 +232,42 @@
|
|
// We have old GC, reuse it and check what
|
|
// we have to change
|
|
|
|
- XGCValues xvalues;
|
|
- unsigned long xvalues_mask=0;
|
|
+ GdkGCValues xvalues;
|
|
+ int xvalues_mask = 0;
|
|
|
|
if (entry->clipRegion) {
|
|
// set it to none here and then set the clip region with
|
|
// gdk_gc_set_clip_region in GetGC()
|
|
xvalues.clip_mask = None;
|
|
- xvalues_mask |= GCClipMask;
|
|
+ xvalues_mask |= GDK_GC_CLIP_MASK;
|
|
gdk_region_destroy(entry->clipRegion);
|
|
entry->clipRegion = NULL;
|
|
}
|
|
|
|
if (entry->gcv.foreground.pixel != gcv->foreground.pixel) {
|
|
- xvalues.foreground = gcv->foreground.pixel;
|
|
- xvalues_mask |= GCForeground;
|
|
+ xvalues.foreground.pixel = gcv->foreground.pixel;
|
|
+ xvalues_mask |= GDK_GC_FOREGROUND;
|
|
}
|
|
|
|
if (entry->gcv.function != gcv->function) {
|
|
- switch (gcv->function) {
|
|
- case GDK_COPY:
|
|
- xvalues.function = GXcopy;
|
|
- break;
|
|
- case GDK_INVERT:
|
|
- xvalues.function = GXinvert;
|
|
- break;
|
|
- case GDK_XOR:
|
|
- xvalues.function = GXxor;
|
|
- break;
|
|
- case GDK_CLEAR:
|
|
- xvalues.function = GXclear;
|
|
- break;
|
|
- case GDK_AND:
|
|
- xvalues.function = GXand;
|
|
- break;
|
|
- case GDK_AND_REVERSE:
|
|
- xvalues.function = GXandReverse;
|
|
- break;
|
|
- case GDK_AND_INVERT:
|
|
- xvalues.function = GXandInverted;
|
|
- break;
|
|
- case GDK_NOOP:
|
|
- xvalues.function = GXnoop;
|
|
- break;
|
|
- case GDK_OR:
|
|
- xvalues.function = GXor;
|
|
- break;
|
|
- case GDK_EQUIV:
|
|
- xvalues.function = GXequiv;
|
|
- break;
|
|
- case GDK_OR_REVERSE:
|
|
- xvalues.function = GXorReverse;
|
|
- break;
|
|
- case GDK_COPY_INVERT:
|
|
- xvalues.function = GXcopyInverted;
|
|
- break;
|
|
- case GDK_OR_INVERT:
|
|
- xvalues.function = GXorInverted;
|
|
- break;
|
|
- case GDK_NAND:
|
|
- xvalues.function = GXnand;
|
|
- break;
|
|
- case GDK_SET:
|
|
- xvalues.function = GXset;
|
|
- break;
|
|
- }
|
|
- xvalues_mask |= GCFunction;
|
|
+ xvalues.function = gcv->function;
|
|
+ xvalues_mask |= GDK_GC_FUNCTION;
|
|
}
|
|
|
|
if(entry->gcv.font != gcv->font && flags & GDK_GC_FONT) {
|
|
- xvalues.font = ((XFontStruct *)GDK_FONT_XFONT(gcv->font))->fid;
|
|
- xvalues_mask |= GCFont;
|
|
+ xvalues.font = gcv->font;
|
|
+ xvalues_mask |= GDK_GC_FONT;
|
|
}
|
|
|
|
if (entry->gcv.line_style != gcv->line_style) {
|
|
- switch (gcv->line_style) {
|
|
- case GDK_LINE_SOLID:
|
|
- xvalues.line_style = LineSolid;
|
|
- break;
|
|
- case GDK_LINE_ON_OFF_DASH:
|
|
- xvalues.line_style = LineOnOffDash;
|
|
- break;
|
|
- case GDK_LINE_DOUBLE_DASH:
|
|
- xvalues.line_style = LineDoubleDash;
|
|
- break;
|
|
- }
|
|
- xvalues_mask |= GCLineStyle;
|
|
+ xvalues.line_style = gcv->line_style;
|
|
+ xvalues_mask |= GDK_GC_LINE_STYLE;
|
|
}
|
|
|
|
if (xvalues_mask != 0) {
|
|
- XChangeGC(GDK_GC_XDISPLAY(entry->gc), GDK_GC_XGC(entry->gc),
|
|
- xvalues_mask, &xvalues);
|
|
+ gdk_gc_set_values(entry->gc, &xvalues, (GdkGCValuesMask)xvalues_mask);
|
|
}
|
|
+
|
|
entry->flags = flags;
|
|
entry->gcv = *gcv;
|
|
}
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp.foo 2004-03-09 09:14:54.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -4600,6 +4600,12 @@
|
|
return mCurrentFont->GetGDKFont();
|
|
}
|
|
|
|
+nsresult
|
|
+nsFontMetricsGTK::SetRightToLeftText(PRBool aIsRTL)
|
|
+{
|
|
+ return NS_OK;
|
|
+}
|
|
+
|
|
PR_BEGIN_EXTERN_C
|
|
static int
|
|
CompareSizes(const void* aArg1, const void* aArg2, void *data)
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsXft.h.foo 2004-02-23 16:38:52.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsXft.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -202,6 +202,8 @@
|
|
|
|
virtual GdkFont* GetCurrentGDKFont(void);
|
|
|
|
+ virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
|
+
|
|
// get hints for the font
|
|
static PRUint32 GetHints (void);
|
|
|
|
--- mozilla/gfx/src/gtk/nsFontMetricsGTK.h.foo 2004-02-04 20:57:03.000000000 -0500
|
|
+++ mozilla/gfx/src/gtk/nsFontMetricsGTK.h 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -344,6 +344,8 @@
|
|
|
|
virtual GdkFont* GetCurrentGDKFont(void);
|
|
|
|
+ virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
|
+
|
|
static nsresult FamilyExists(nsIDeviceContext *aDevice, const nsString& aName);
|
|
static PRUint32 GetHints(void);
|
|
|
|
--- mozilla/configure.in.foo 2004-11-22 12:55:08.000000000 -0500
|
|
+++ mozilla/configure.in 2004-11-22 12:56:21.000000000 -0500
|
|
@@ -3476,6 +3476,34 @@
|
|
AC_SUBST(MOZ_XFT_LIBS)
|
|
|
|
dnl ========================================================
|
|
+dnl = pango font rendering
|
|
+dnl ========================================================
|
|
+MOZ_ARG_ENABLE_BOOL(pango,
|
|
+[ --enable-pango Enable Pango font rendering support],
|
|
+ MOZ_ENABLE_PANGO=1,
|
|
+ MOZ_ENABLE_PANGO=)
|
|
+
|
|
+if test "$MOZ_ENABLE_PANGO"
|
|
+then
|
|
+ AC_DEFINE(MOZ_ENABLE_PANGO)
|
|
+ PKG_CHECK_MODULES(MOZ_PANGO, pango >= 1.5.0)
|
|
+
|
|
+ dnl Make sure that the pango version is _actually_ new enough
|
|
+ _SAVE_CFLAGS=$CFLAGS
|
|
+ _SAVE_LDFLAGS=$LDFLAGS
|
|
+ CFLAGS="$MOZ_PANGO_CFLAGS $CFLAGS"
|
|
+ LDFLAGS="$MOZ_PANGO_LIBS $LDFLAGS"
|
|
+ AC_CHECK_LIB(pangoft2-1.0, pango_fc_font_map_add_decoder_find_func,,
|
|
+ AC_MSG_ERROR([Your Pango is too old. Sorry.]))
|
|
+ CFLAGS=$_SAVE_CFLAGS
|
|
+ LDFLAGS=$_SAVE_LDFLAGS
|
|
+
|
|
+ AC_SUBST(MOZ_ENABLE_PANGO)
|
|
+ AC_SUBST(MOZ_PANGO_CFLAGS)
|
|
+ AC_SUBST(MOZ_PANGO_LIBS)
|
|
+fi
|
|
+
|
|
+dnl ========================================================
|
|
dnl = disabling x11 core support, enabled by default
|
|
dnl ========================================================
|
|
MOZ_ENABLE_COREXFONTS=${MOZ_ENABLE_COREXFONTS-1}
|