New version gfxQtFontGroup (kerning & missing glyph support)
authorpekka.aho
Sat, 19 Apr 2008 18:39:34 +0300
changeset 16819 19f33c4045006c872e8faa1e7d27620f6a3d8c5d
parent 16818 2c69b5cd65bae00652a3be5625fee00ee2c42aef
child 16820 2e3a6e7d8293c91746cf153dd535436d9fc8150d
push id1298
push userpavlov@mozilla.com
push dateSun, 17 Aug 2008 05:03:09 +0000
treeherderautoland@4a506fa751d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0a1pre
New version gfxQtFontGroup (kerning & missing glyph support)
gfx/thebes/public/gfxQtFonts.h
gfx/thebes/src/gfxQtFonts.cpp
--- a/gfx/thebes/public/gfxQtFonts.h
+++ b/gfx/thebes/public/gfxQtFonts.h
@@ -48,27 +48,29 @@
 #include "nsClassHashtable.h"
 
 #define ENABLE_FAST_PATH_8BIT 1
 #define ENABLE_FAST_PATH_ALWAYS 1
 
 class QFont;
 
 class gfxQtFont : public gfxFont {
-public:
-     gfxQtFont (const nsAString& aName,
-                const gfxFontStyle *aFontStyle);
-     virtual ~gfxQtFont ();
+public: // new functions
+    gfxQtFont (const nsAString& aName,
+            const gfxFontStyle *aFontStyle);
+    virtual ~gfxQtFont ();
 
-     inline const QFont& GetQFont();
+    inline const QFont& GetQFont();
+
+public: // from gfxFont
+    virtual PRUint32 GetSpaceGlyph ();
+    virtual const gfxFont::Metrics& GetMetrics();
 
 protected: // from gfxFont
     virtual nsString GetUniqueName ();
-    virtual PRUint32 GetSpaceGlyph ();
-    virtual const gfxFont::Metrics& GetMetrics();
     virtual PRBool SetupCairoFont(gfxContext *aContext);
 
 protected: // new functions
     cairo_scaled_font_t* CreateScaledFont(cairo_t *aCR, 
                                           cairo_matrix_t *aCTM, 
                                           QFont &aQFont);
 
 protected: // data
@@ -80,54 +82,59 @@ protected: // data
     PRUint32 mSpaceGlyph;
     PRBool mHasMetrics;
     Metrics mMetrics;
     gfxFloat mAdjustedSize;
 
 };
 
 class THEBES_API gfxQtFontGroup : public gfxFontGroup {
-public:
+public: // new functions
     gfxQtFontGroup (const nsAString& families,
                     const gfxFontStyle *aStyle);
     virtual ~gfxQtFontGroup ();
 
+    inline gfxQtFont * GetFontAt (PRInt32 i);
+
+protected: // from gfxFontGroup
+    virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
+    virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
     virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
 
-    // Create and initialize a textrun using Pango
-    virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
-                                    const Parameters *aParams, PRUint32 aFlags);
-    virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
-                                    const Parameters *aParams, PRUint32 aFlags);
 
-    gfxQtFont * GetFontAt (PRInt32 i) {
-        return static_cast < gfxQtFont * >(static_cast < gfxFont * >(mFonts[i]));
-    }
+protected: // new functions
+    void InitTextRun(gfxTextRun *aTextRun, 
+                     const PRUint8 *aUTF8Text,
+                     PRUint32 aUTF8Length, 
+                     PRUint32 aUTF8HeaderLength);
 
-protected:
-    void InitTextRun (gfxTextRun * aTextRun, const char * aUTF8Text,
-                      PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
-                      PRBool aTake8BitPath);
+    void CreateGlyphRunsFT(gfxTextRun *aTextRun, 
+                           const PRUint8 *aUTF8,
+                           PRUint32 aUTF8Length);
 
-/*
-    void CreateGlyphRunsItemizing (gfxTextRun * aTextRun,
-                                   const char * aUTF8, PRUint32 aUTF8Length,
-                                   PRUint32 aUTF8HeaderLength);
-*/
-#if defined(ENABLE_FAST_PATH_8BIT) || defined(ENABLE_FAST_PATH_ALWAYS)
-    PRBool CanTakeFastPath (PRUint32 aFlags);
-    nsresult CreateGlyphRunsFast (gfxTextRun * aTextRun,
-                                  const char * aUTF8, PRUint32 aUTF8Length);
-#endif
-
-
-    static PRBool FontCallback (const nsAString & fontName, const nsACString & genericName, void *closure);
+    static PRBool FontCallback (const nsAString & fontName, 
+                                const nsACString & genericName, 
+                                void *closure);
+    PRBool mEnableKerning;
 
 };
 
 inline const QFont& gfxQtFont::GetQFont()
 {
     return *mQFont;
 }
 
+inline gfxQtFont * gfxQtFontGroup::GetFontAt (PRInt32 i) 
+{
+    return static_cast < gfxQtFont * >(static_cast < gfxFont * >(mFonts[i]));
+}
+
 
 #endif /* GFX_QTFONTS_H */
 
--- a/gfx/thebes/src/gfxQtFonts.cpp
+++ b/gfx/thebes/src/gfxQtFonts.cpp
@@ -14,24 +14,16 @@
  *
  * The Original Code is Mozilla Foundation code.
  *
  * The Initial Developer of the Original Code is Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2005
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Vladimir Vukicevic <vladimir@mozilla.com>
- *   Masayuki Nakano <masayuki@d-toybox.com>
- *   Behdad Esfahbod <behdad@gnome.org>
- *   Mats Palmgren <mats.palmgren@bredband.net>
- *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
- *
- * based on nsFontMetricsPango.cpp by
- *   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
@@ -126,21 +118,16 @@ gfxQtFontGroup::gfxQtFontGroup (const ns
             fcFamilies.Append(*familyArray[i]);
             ++i;
             if (i >= familyArray.Count())
                 break;
             fcFamilies.Append(NS_LITERAL_STRING(","));
         }
     }
     else {
-        // XXX If there are no fonts, we should use dummy family.
-        // Pango will resolve from this.
-        // behdad: yep, looks good.
-        // printf("%s(%s)\n", NS_ConvertUTF16toUTF8(families).get(),
-        //                    aStyle->langGroup.get());
         fcFamilies.Append(NS_LITERAL_STRING("sans-serif"));
     }
 
     nsRefPtr<gfxQtFont> font = GetOrMakeFont(fcFamilies, &mStyle);
     if (font) {
         mFonts.AppendElement(font);
     }
 }
@@ -150,265 +137,241 @@ gfxQtFontGroup::~gfxQtFontGroup()
 }
 
 gfxFontGroup *
 gfxQtFontGroup::Copy(const gfxFontStyle *aStyle)
 {
      return new gfxQtFontGroup(mFamilies, aStyle);
 }
 
-#if defined(ENABLE_FAST_PATH_8BIT)
-PRBool
-gfxQtFontGroup::CanTakeFastPath(PRUint32 aFlags)
+/**
+ * We use this to append an LTR or RTL Override character to the start of the
+ * string. This forces Pango to honour our direction even if there are neutral
+ * characters in the string.
+ */
+static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
 {
-    // Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't.
-    // We need to always use Pango for RTL text, in case glyph mirroring is
-    // required.
-    PRBool speed = aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
-    PRBool isRTL = aFlags & gfxTextRunFactory::TEXT_IS_RTL;
-    return speed && !isRTL
-           //&& PANGO_IS_FC_FONT(GetFontAt(0)->GetPangoFont())
-           ;
+    static const PRUnichar overrides[2][2] = { { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO
+    AppendUTF16toUTF8(overrides[aIsRTL], aString);
+    return 3; // both overrides map to 3 bytes in UTF8
 }
-#endif
+
+gfxTextRun *gfxQtFontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
+                                         const Parameters* aParams, PRUint32 aFlags)
+{
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    mEnableKerning = !(aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED);
+
+    textRun->RecordSurrogates(aString);
+
+    nsCAutoString utf8;
+    PRInt32 headerLen = AppendDirectionalIndicatorUTF8(textRun->IsRightToLeft(), utf8);
+    AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8);
+
+    InitTextRun(textRun, (PRUint8 *)utf8.get(), utf8.Length(), headerLen);
 
-#if defined(ENABLE_FAST_PATH_8BIT) || defined(ENABLE_FAST_PATH_ALWAYS)
-#define UTF8_COMPUTE(Char, Mask, Len)					      \
-  if (Char < 128)							      \
-    {									      \
-      Len = 1;								      \
-      Mask = 0x7f;							      \
-    }									      \
-  else if ((Char & 0xe0) == 0xc0)					      \
-    {									      \
-      Len = 2;								      \
-      Mask = 0x1f;							      \
-    }									      \
-  else if ((Char & 0xf0) == 0xe0)					      \
-    {									      \
-      Len = 3;								      \
-      Mask = 0x0f;							      \
-    }									      \
-  else if ((Char & 0xf8) == 0xf0)					      \
-    {									      \
-      Len = 4;								      \
-      Mask = 0x07;							      \
-    }									      \
-  else if ((Char & 0xfc) == 0xf8)					      \
-    {									      \
-      Len = 5;								      \
-      Mask = 0x03;							      \
-    }									      \
-  else if ((Char & 0xfe) == 0xfc)					      \
-    {									      \
-      Len = 6;								      \
-      Mask = 0x01;							      \
-    }									      \
-  else									      \
-    Len = -1;
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
+
+gfxTextRun *gfxQtFontGroup::MakeTextRun(const PRUint8* aString, PRUint32 aLength,
+                                         const Parameters* aParams, PRUint32 aFlags)
+{
+    NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    mEnableKerning = !(aFlags & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED);
 
-#define UTF8_GET(Result, Chars, Count, Mask, Len)			      \
-  (Result) = (Chars)[0] & (Mask);					      \
-  for ((Count) = 1; (Count) < (Len); ++(Count))				      \
-    {									      \
-      if (((Chars)[(Count)] & 0xc0) != 0x80)				      \
-	{								      \
-	  (Result) = -1;						      \
-	  break;							      \
-	}								      \
-      (Result) <<= 6;							      \
-      (Result) |= ((Chars)[(Count)] & 0x3f);				      \
+    const char *chars = reinterpret_cast<const char *>(aString);
+    PRBool isRTL = textRun->IsRightToLeft();
+    if ((aFlags & TEXT_IS_ASCII) && !isRTL) {
+        // We don't need to send an override character here, the characters must be all
+        // LTR
+        InitTextRun(textRun, (PRUint8 *)chars, aLength, 0);
+    } else {
+        // Although chars in not necessarily ASCII (as it may point to the low
+        // bytes of any UCS-2 characters < 256), NS_ConvertASCIItoUTF16 seems
+        // to DTRT.
+        NS_ConvertASCIItoUTF16 unicodeString(chars, aLength);
+        nsCAutoString utf8;
+        PRInt32 headerLen = AppendDirectionalIndicatorUTF8(isRTL, utf8);
+        AppendUTF16toUTF8(unicodeString, utf8);
+        InitTextRun(textRun, (PRUint8 *)utf8.get(), utf8.Length(), headerLen);
     }
 
-static const char utf8_skip_data[256] = {
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
-};
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
 
-const char * const g_utf8_skip = utf8_skip_data;
-#define g_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(const unsigned char *)(p)])
-
-int
-g_utf8_get_char (const char *p)
+void gfxQtFontGroup::InitTextRun(gfxTextRun *aTextRun, const PRUint8 *aUTF8Text,
+                                  PRUint32 aUTF8Length,
+                                  PRUint32 aUTF8HeaderLength)
 {
-  int i, mask = 0, len;
-  int result;
-  unsigned char c = (unsigned char) *p;
-
-  UTF8_COMPUTE (c, mask, len);
-  if (len == -1)
-    return (int)-1;
-  UTF8_GET (result, p, i, mask, len);
-  return result;
+    CreateGlyphRunsFT(aTextRun, aUTF8Text + aUTF8HeaderLength,
+                      aUTF8Length - aUTF8HeaderLength);
 }
 
-nsresult
-gfxQtFontGroup::CreateGlyphRunsFast(gfxTextRun *aTextRun,
-                                    const char *aUTF8, PRUint32 aUTF8Length)
+// Helper function to return the leading UTF-8 character in a char pointer
+// as 32bit number. Also sets the length of the current character (i.e. the
+// offset to the next one) in the second argument
+PRUint32 getUTF8CharAndNext(const PRUint8 *aString, PRUint8 *aLength)
 {
-    const char *p = aUTF8;
-    gfxQtFont *font = GetFontAt(0);
-    const QFont& qFont = font->GetQFont();
-    FT_Face face = qFont.freetypeFace();
+    *aLength = 1;
+    if (aString[0] < 0x80) { // normal 7bit ASCII char
+        return aString[0];
+    }
+    if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes
+        *aLength = 2;
+        return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes
+        *aLength = 3;
+        return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) +
+               (aString[2] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes
+        *aLength = 4;
+        return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) +
+               ((aString[2] & 0x3F) <<  6) + (aString[3] & 0x3F);
+    }
+    return aString[0];
+}
+
+void gfxQtFontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun, const PRUint8 *aUTF8,
+                                        PRUint32 aUTF8Length)
+{
+
+    PRUint32 fontlistLast = FontListLength()-1;
+    gfxQtFont *font0 = GetFontAt(0);
+    const PRUint8 *p = aUTF8;
     PRUint32 utf16Offset = 0;
     gfxTextRun::CompressedGlyph g;
     const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
 
-    aTextRun->AddGlyphRun(font, 0);
-
+    aTextRun->AddGlyphRun(font0, 0);
+    // a textRun likely has the same font for most of the characters, so we can
+    // lock it before the loop for efficiency
+    FT_Face face0 =  font0->GetQFont().freetypeFace();
     while (p < aUTF8 + aUTF8Length) {
-        // glib-2.12.9: "If p does not point to a valid UTF-8 encoded
-        // character, results are undefined." so it is not easy to assert that
-        // aUTF8 in fact points to UTF8 data but asserting
-        // g_unichar_validate(ch) may be mildly useful.
-        int ch = g_utf8_get_char(p);
-        p = g_utf8_next_char(p);
+        PRBool glyphFound = PR_FALSE;
+        // convert UTF-8 character and step to the next one in line
+        PRUint8 chLen;
+        PRUint32 ch = getUTF8CharAndNext(p, &chLen);
+        p += chLen; // move to next char
 
         if (ch == 0) {
-            // treat this null byte as a missing glyph. Pango
-            // doesn't create glyphs for these, not even missing-glyphs.
+            // treat this null byte as a missing glyph, don't create a glyph for it
             aTextRun->SetMissingGlyph(utf16Offset, 0);
         } else {
-            NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
-            int glyph = 124;
-            glyph = FT_Get_Char_Index (face, ch);
+            // Try to get a glyph from all fonts available to us.
+            // Once we found it in one of the fonts we quit the loop early.
+            // If we don't find the glyph, we set the missing glyph symbol after
+            // trying the last font.
+            for (PRUint32 i = 0; i <= fontlistLast; i++) {
+                gfxQtFont *font = font0;
+                FT_Face face = face0;
+                if (i > 0) {
+                    font = GetFontAt(i);
+                    face = font->GetQFont().freetypeFace();
+                }
+                // select the current font into the text run
+                aTextRun->AddGlyphRun(font, utf16Offset);
 
-            if (!glyph)                  // character not in font,
-                return NS_ERROR_FAILURE; // fallback to CreateGlyphRunsItemizing
+                NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
+                FT_UInt gid = FT_Get_Char_Index(face, ch); // find the glyph id
+                PRInt32 advance = 0;
+                if (gid == font->GetSpaceGlyph()) {
+                    advance = (int)(font->GetMetrics().spaceWidth * appUnitsPerDevUnit);
+                } else if (gid == 0) {
+                    advance = -1; // trigger the missing glyphs case below
+                } else {
+                    // find next character and its glyph -- in case they exist
+                    // and exist in the current font face -- to compute kerning
+                    PRUint32 chNext = 0;
+                    FT_UInt gidNext = 0;
+                    FT_Pos lsbDeltaNext = 0;
+                    if (mEnableKerning && FT_HAS_KERNING(face) && p < aUTF8 + aUTF8Length) {
+                        chNext = getUTF8CharAndNext(p, &chLen);
+                        if (chNext) {
+                            gidNext = FT_Get_Char_Index(face, chNext);
+                            if (gidNext && gidNext != font->GetSpaceGlyph()) {
+                                FT_Load_Glyph(face, gidNext, FT_LOAD_DEFAULT);
+                                lsbDeltaNext = face->glyph->lsb_delta;
+                            }
+                        }
+                    }
 
-            FT_Load_Glyph(face, glyph, FT_LOAD_DEFAULT);
-            PRInt32 advance = face->glyph->advance.x;
-            advance = (advance >> 6) * appUnitsPerDevUnit;
+                    // now load the current glyph
+                    FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load glyph into the slot
+                    advance = face->glyph->advance.x;
 
-            if (advance >= 0 &&
-                gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
-                gfxTextRun::CompressedGlyph::IsSimpleGlyphID(glyph)) {
-                aTextRun->SetSimpleGlyph(utf16Offset,
-                                         g.SetSimpleGlyph(advance, glyph));
-            } else {
-                gfxTextRun::DetailedGlyph details;
-                details.mGlyphID = glyph;
-                NS_ASSERTION(details.mGlyphID == glyph,
-                             "Seriously weird glyph ID detected!");
-                details.mAdvance = advance;
-                details.mXOffset = 0;
-                details.mYOffset = 0;
-                g.SetComplex(aTextRun->IsClusterStart(utf16Offset), PR_TRUE, 1);
-                aTextRun->SetGlyphs(utf16Offset, g, &details);
+                    // now add kerning to the current glyph's advance
+                    if (chNext && gidNext) {
+                        FT_Vector kerning;
+                        FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
+                        advance += kerning.x;
+                        if (face->glyph->rsb_delta - lsbDeltaNext >= 32) {
+                            advance -= 64;
+                        } else if (face->glyph->rsb_delta - lsbDeltaNext < -32) {
+                            advance += 64;
+                        }
+                    }
+
+                    // now apply unit conversion and scaling
+                    advance = (advance >> 6) * appUnitsPerDevUnit;
+                }
+
+                if (advance >= 0 &&
+                    gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
+                    gfxTextRun::CompressedGlyph::IsSimpleGlyphID(gid))
+                {
+                    aTextRun->SetSimpleGlyph(utf16Offset,
+                                             g.SetSimpleGlyph(advance, gid));
+                    glyphFound = PR_TRUE;
+                } else if (gid == 0) {
+                    // gid = 0 only happens when the glyph is missing from the font
+                    if (i == fontlistLast) {
+                        // set the missing glyph only when it's missing from the very
+                        // last font
+                        aTextRun->SetMissingGlyph(utf16Offset, ch);
+                    }
+                    glyphFound = PR_FALSE;
+                } else {
+                    gfxTextRun::DetailedGlyph details;
+                    details.mGlyphID = gid;
+                    NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!");
+                    details.mAdvance = advance;
+                    details.mXOffset = 0;
+                    details.mYOffset = 0;
+                    g.SetComplex(aTextRun->IsClusterStart(utf16Offset), PR_TRUE, 1);
+                    aTextRun->SetGlyphs(utf16Offset, g, &details);
+                    glyphFound = PR_TRUE;
+                }
+
+                if (glyphFound) {
+                    break;
+                }
             }
+        } // for all fonts
 
-            NS_ASSERTION(!IS_SURROGATE(ch), "Surrogates shouldn't appear in UTF8");
-            if (ch >= 0x10000) {
-                // This character is a surrogate pair in UTF16
-                ++utf16Offset;
-            }
+        NS_ASSERTION(!IS_SURROGATE(ch), "Surrogates shouldn't appear in UTF8");
+        if (ch >= 0x10000) {
+            // This character is a surrogate pair in UTF16
+            ++utf16Offset;
         }
 
         ++utf16Offset;
     }
-    return NS_OK;
-}
-#endif
-
-
-void
-gfxQtFontGroup::InitTextRun(gfxTextRun *aTextRun, const char *aUTF8Text,
-                             PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
-                             PRBool aTake8BitPath)
-{
-#if defined(ENABLE_FAST_PATH_ALWAYS)
-    CreateGlyphRunsFast(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
-#else
-#if defined(ENABLE_FAST_PATH_8BIT)
-    if (aTake8BitPath && CanTakeFastPath(aTextRun->GetFlags())) {
-        qDebug("QTFONT NOT_IMPLEMENTED!!!! Func:%s::%d, Text:'%s'\n", __PRETTY_FUNCTION__, __LINE__, aUTF8Text);
-//        nsresult rv = CreateGlyphRunsFast(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
-        if (NS_SUCCEEDED(rv))
-            return;
-    }
-#endif
-      qDebug("QTFONT NOT_IMPLEMENTED!!!! Func:%s::%d, Text:'%s'\n", __PRETTY_FUNCTION__, __LINE__, aUTF8Text);
-//    CreateGlyphRunsItemizing(aTextRun, aUTF8Text, aUTF8Length, aUTF8HeaderLength);
-#endif
-}
-
-/**
- * We use this to append an LTR or RTL Override character to the start of the
- * string. This forces Pango to honour our direction even if there are neutral characters
- * in the string.
- */
-static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
-{
-    static const PRUnichar overrides[2][2] =
-      { { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO
-    AppendUTF16toUTF8(overrides[aIsRTL], aString);
-    return 3; // both overrides map to 3 bytes in UTF8
-}
-
-gfxTextRun *
-gfxQtFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
-                               const Parameters *aParams, PRUint32 aFlags)
-{
-    NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
-    gfxTextRun *run = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
-    if (!run)
-        return nsnull;
-
-    PRBool isRTL = run->IsRightToLeft();
-    if ((aFlags & TEXT_IS_ASCII) && !isRTL) {
-        // We don't need to send an override character here, the characters must be all LTR
-        const char *utf8Chars = reinterpret_cast<const char*>(aString);
-        InitTextRun(run, utf8Chars, aLength, 0, PR_TRUE);
-    } else {
-        // this is really gross...
-        const char *chars = reinterpret_cast<const char*>(aString);
-        NS_ConvertASCIItoUTF16 unicodeString(chars, aLength);
-        nsCAutoString utf8;
-        PRInt32 headerLen = AppendDirectionalIndicatorUTF8(isRTL, utf8);
-        AppendUTF16toUTF8(unicodeString, utf8);
-        InitTextRun(run, utf8.get(), utf8.Length(), headerLen, PR_TRUE);
-    }
-    run->FetchGlyphExtents(aParams->mContext);
-    return run;
-}
-
-gfxTextRun *
-gfxQtFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
-                               const Parameters *aParams, PRUint32 aFlags)
-{
-    gfxTextRun *run = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
-    if (!run)
-        return nsnull;
-
-    run->RecordSurrogates(aString);
-
-    nsCAutoString utf8;
-    PRInt32 headerLen = AppendDirectionalIndicatorUTF8(run->IsRightToLeft(), utf8);
-    AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8);
-    PRBool is8Bit = PR_FALSE;
-
-#if defined(ENABLE_FAST_PATH_8BIT)
-    if (CanTakeFastPath(aFlags)) {
-        PRUint32 allBits = 0;
-        PRUint32 i;
-        for (i = 0; i < aLength; ++i) {
-            allBits |= aString[i];
-        }
-        is8Bit = (allBits & 0xFF00) == 0;
-    }
-#endif
-    InitTextRun(run, utf8.get(), utf8.Length(), headerLen, is8Bit);
-    run->FetchGlyphExtents(aParams->mContext);
-    return run;
 }
 
 /**
  * gfxQtFont
  */
 gfxQtFont::gfxQtFont(const nsAString &aName,
                      const gfxFontStyle *aFontStyle)
     : gfxFont(aName, aFontStyle),
@@ -416,17 +379,17 @@ gfxQtFont::gfxQtFont(const nsAString &aN
       mCairoFont(nsnull),
       mHasSpaceGlyph(PR_FALSE),
       mSpaceGlyph(0),
       mHasMetrics(PR_FALSE), 
       mAdjustedSize(0)
 {
     mQFont = new QFont();
     mQFont->setFamily(QString( NS_ConvertUTF16toUTF8(mName).get() ) );
-    mQFont->setPixelSize((int) GetStyle()->size);
+    mQFont->setPixelSize(GetStyle()->size);
     int weight = GetStyle()->weight/10;
     if( weight > 99 )
     {
         // Max Weight for QFont is 99
         weight = 99;
     }
     mQFont->setWeight(weight);
     mQFont->setItalic(bool( GetStyle()->style == FONT_STYLE_ITALIC ));
@@ -473,18 +436,18 @@ gfxQtFont::GetMetrics()
     mMetrics.emAscent = lineHeight > 0.0 ?
         mMetrics.maxAscent * mMetrics.emHeight / lineHeight : 0.0;
     mMetrics.emDescent = mMetrics.emHeight - mMetrics.emAscent;
 
     mMetrics.spaceWidth = fontMetrics.width( QChar(' ') );
     mMetrics.xHeight = fontMetrics.xHeight();
 
 
-	mMetrics.superscriptOffset = mMetrics.xHeight;
-	mMetrics.subscriptOffset = mMetrics.xHeight;
+    mMetrics.superscriptOffset = mMetrics.xHeight;
+    mMetrics.subscriptOffset = mMetrics.xHeight;
 
 
   
 #if 0
 
     fprintf (stderr, "Font: %s\n", NS_ConvertUTF16toUTF8(mName).get());
     fprintf (stderr, "    emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
     fprintf (stderr, "    maxAscent: %f maxDescent: %f\n", mMetrics.maxAscent, mMetrics.maxDescent);