[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

vestbo at webkit.org vestbo at webkit.org
Thu Apr 8 00:47:34 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit e3e57acbd948e65b20e11dbd694a6ea2dcd92480
Author: vestbo at webkit.org <vestbo at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Dec 23 12:52:15 2009 +0000

    Fix for newlines turning into missing-gyphs when using SVG fonts
    
    Reviewed by Darin Adler.
    
    https://bugs.webkit.org/show_bug.cgi?id=32710
    
    Font::drawText() has three code paths:
    
      - drawTextUsingSVGFont()
      - drawSimpleText()
      - drawComplexText()
    
    The latter two both have logic to replace newlines and tabs, as well
    as a few other control characters that are considered spaces, with
    spaces, before actually drawing the text. Previously the SVG font
    path did not have this kind of logic.
    
    This change introduces two helper functions in Font to do this space
    replacement, which are then used for the simple path, the SVG path,
    and the Qt implementation of the complex path.
    
    Test: svg/custom/svg-fonts-in-html-linebreaks.html
    
    WebCore:
    
    * platform/graphics/Font.cpp:
    (WebCore::Font::normalizeSpaces): Helper function
    * platform/graphics/Font.h:
    * platform/graphics/FontFastPath.cpp:
    (WebCore::Font::glyphDataForCharacter): Use helper
    * platform/graphics/qt/FontQt.cpp:
    (WebCore::fromRawDataWithoutRef): Rename from "qstring"
    (WebCore::Font::drawComplexText): Use helper
    (WebCore::Font::floatWidthForComplexText): Use helper
    (WebCore::Font::offsetForPositionForComplexText): Use helper
    (WebCore::Font::selectionRectForComplexText): Use helper
    * platform/text/CharacterNames.h: Add enum for 0x0020
    * svg/SVGFont.cpp: Use helper to fix bug
    (WebCore::SVGTextRunWalker::walk):
    
    LayoutTests:
    
    * svg/custom/resources/ABCFont.svg: Added. Font for test case
    * svg/custom/svg-fonts-in-html-linebreaks-expected.txt: Added.
    * svg/custom/svg-fonts-in-html-linebreaks.html: New test case
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52525 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 6c0e442..553c495 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,32 @@
+2009-12-18  Tor Arne Vestbø  <tor.arne.vestbo at nokia.com>
+
+        Reviewed by Darin Adler.
+
+        Fix for newlines turning into missing-gyphs when using SVG fonts
+
+        https://bugs.webkit.org/show_bug.cgi?id=32710
+
+        Font::drawText() has three code paths:
+
+          - drawTextUsingSVGFont()
+          - drawSimpleText()
+          - drawComplexText()
+
+        The latter two both have logic to replace newlines and tabs, as well
+        as a few other control characters that are considered spaces, with
+        spaces, before actually drawing the text. Previously the SVG font
+        path did not have this kind of logic.
+
+        This change introduces two helper functions in Font to do this space
+        replacement, which are then used for the simple path, the SVG path,
+        and the Qt implementation of the complex path.
+
+        Test: svg/custom/svg-fonts-in-html-linebreaks.html
+
+        * svg/custom/resources/ABCFont.svg: Added. Font for test case
+        * svg/custom/svg-fonts-in-html-linebreaks-expected.txt: Added.
+        * svg/custom/svg-fonts-in-html-linebreaks.html: New test case
+
 2009-12-23  Kent Tamura  <tkent at chromium.org>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/svg/custom/resources/ABCFont.svg b/LayoutTests/svg/custom/resources/ABCFont.svg
new file mode 100644
index 0000000..f05358d
--- /dev/null
+++ b/LayoutTests/svg/custom/resources/ABCFont.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <!-- Based on DejaVu Serif (http://dejavu-fonts.org/wiki/index.php?title=License) -->
+        <font id="ABCFont" horiz-adv-x="1716">
+            <font-face
+                font-family="DejaVu Serif"
+                font-weight="400"
+                font-stretch="normal"
+                units-per-em="2048"
+                panose-1="2 6 6 3 5 6 5 2 2 4"
+                ascent="1556"
+                descent="-492"
+                x-height="1063"
+                cap-height="1493"
+                bbox="-1576 -710 3439 2544"
+                underline-thickness="90"
+                underline-position="-85"
+                unicode-range="U+0020-U+1D7E1"
+            />
+
+            <missing-glyph horiz-adv-x="1229" d="M102 -362v1806h1024v-1806h-1024zM217 -248h795v1577h-795v-1577z" />
+
+            <glyph glyph-name="space" unicode=" " horiz-adv-x="651" />
+
+            <glyph glyph-name="a" unicode="a" horiz-adv-x="1221"
+                d="M815 334v225h-237q-137 0 -204 -59t-67 -181q0 -111 68 -176t184 -65q115 0 185.5 71t70.5 185zM999 664v-558h164v-106h-348v115q-61 -74 -141 -109t-187 -35q-177 0 -281 94t-104 254q0 165 119 256t336 91h258v73q0 121 -73.5 187.5t-206.5 66.5q-110 0 -175 -50t-81 -148h-95v215q96 41 186.5 61.5t176.5 20.5q221 0 336.5 -109.5t115.5 -318.5z" />
+            <glyph glyph-name="b" unicode="b" horiz-adv-x="1311"
+                d="M236 106v1344h-177v106h361v-659q54 100 137.5 147.5t206.5 47.5q196 0 320 -155t124 -405t-124 -405.5t-320 -155.5q-123 0 -206.5 47.5t-137.5 147.5v-166h-361v106h177zM420 479q0 -192 73.5 -292.5t213.5 -100.5q141 0 213.5 113t72.5 333q0 221 -72.5 333t-213.5 112q-140 0 -213.5 -101t-73.5 -292v-105z" />
+            <glyph glyph-name="c" unicode="c" horiz-adv-x="1147"
+                d="M1053 319q-39 -170 -150 -259t-287 -89q-232 0 -373 153.5t-141 407.5q0 255 141 407.5t373 152.5q101 0 201 -23.5t201 -71.5v-272h-107q-21 140 -91.5 204t-201.5 64q-149 0 -225 -115.5t-76 -345.5t75.5 -346t225.5 -116q119 0 190 62t97 187h148z" />
+        </font>
+    </defs>
+</svg>
\ No newline at end of file
diff --git a/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks-expected.txt b/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks-expected.txt
new file mode 100644
index 0000000..95dff11
--- /dev/null
+++ b/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks-expected.txt
@@ -0,0 +1,11 @@
+This test is to ensure that text rendered with a SVG-font has the same behavior for handling control characters like newlines, as text rendered though the normal (fast or complex) path. The two "a b c" strings below should have the same length and not produce any missing-glyph symbols.
+
+a b c <--- This text has line breaks in the source HTML ("\n")
+a b c <--- This text has no line breaks (just "a b c")
+
+As a reference, this is how normal text looks like for the same usecase:
+
+a b c <--- This text has line breaks in the source HTML ("\n")
+a b c <--- This text has no line breaks (just "a b c")
+
+PASS
diff --git a/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks.html b/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks.html
new file mode 100644
index 0000000..8b6826c
--- /dev/null
+++ b/LayoutTests/svg/custom/svg-fonts-in-html-linebreaks.html
@@ -0,0 +1,77 @@
+<head>
+
+<style type="text/css" media="all">
+ at font-face {
+    font-family: ABCFont;
+    src: url(resources/ABCFont.svg#ABCFont) format('svg');
+}
+
+span {
+    margin-right: 10px;
+}
+</style>
+
+<script type="text/javascript">
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function log(msg)
+{
+    var div = document.createElement("div");
+    div.innerHTML = msg;
+    document.getElementById("console").appendChild(div);
+}
+
+function run()
+{
+    var withLinebreaks = document.getElementById("svg-with-linebreaks");
+    var withoutLinebreaks = document.getElementById("svg-without-linebreaks");
+
+    if (withLinebreaks.offsetWidth == withoutLinebreaks.offsetWidth) {
+        log("<span style='color: green'>PASS</span>");
+    } else {
+        log("<span style='color: red'>FAIL</span>("
+                + withLinebreaks.offsetWidth + "px != "+ withoutLinebreaks.offsetWidth + "px)");
+    }
+
+    layoutTestController.notifyDone();
+}
+</script>
+
+</head>
+
+<body onload="setTimeout('run()', 200)">
+
+<p>This test is to ensure that text rendered with a SVG-font has the same behavior for handling
+control characters like newlines, as text rendered though the normal (fast or complex) path.
+The two "a b c" strings below should have the same length and not produce any missing-glyph symbols.</p>
+<div>
+<span id="svg-with-linebreaks" style="font-family: ABCFont">a
+b
+c</span>
+<span>&#60;--- This text has line breaks in the source HTML ("\n")</span>
+</div>
+<div>
+<span id="svg-without-linebreaks" style="font-family: ABCFont">a b c</span>
+<span>&#60;--- This text has no line breaks (just "a b c")</span>
+</div>
+<br>
+<div>As a reference, this is how normal text looks like for the same usecase:</div
+<br>
+<div>
+<span id="normal-with-linebreaks">a
+b
+c</span>
+<span>&#60;--- This text has line breaks in the source HTML ("\n")</span>
+</div>
+<div>
+<span id="normal-without-linebreaks">a b c</span>
+<span>&#60;--- This text has no line breaks (just "a b c")</span>
+</div>
+<br>
+<div id="console"></div>
+</body>
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 22226eb..63cffb6 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,43 @@
+2009-12-18  Tor Arne Vestbø  <tor.arne.vestbo at nokia.com>
+
+        Reviewed by Darin Adler.
+
+        Fix for newlines turning into missing-gyphs when using SVG fonts
+
+        https://bugs.webkit.org/show_bug.cgi?id=32710
+
+        Font::drawText() has three code paths:
+
+          - drawTextUsingSVGFont()
+          - drawSimpleText()
+          - drawComplexText()
+
+        The latter two both have logic to replace newlines and tabs, as well
+        as a few other control characters that are considered spaces, with
+        spaces, before actually drawing the text. Previously the SVG font
+        path did not have this kind of logic.
+
+        This change introduces two helper functions in Font to do this space
+        replacement, which are then used for the simple path, the SVG path,
+        and the Qt implementation of the complex path.
+
+        Test: svg/custom/svg-fonts-in-html-linebreaks.html
+
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::normalizeSpaces): Helper function
+        * platform/graphics/Font.h:
+        * platform/graphics/FontFastPath.cpp:
+        (WebCore::Font::glyphDataForCharacter): Use helper
+        * platform/graphics/qt/FontQt.cpp:
+        (WebCore::fromRawDataWithoutRef): Rename from "qstring"
+        (WebCore::Font::drawComplexText): Use helper
+        (WebCore::Font::floatWidthForComplexText): Use helper
+        (WebCore::Font::offsetForPositionForComplexText): Use helper
+        (WebCore::Font::selectionRectForComplexText): Use helper
+        * platform/text/CharacterNames.h: Add enum for 0x0020
+        * svg/SVGFont.cpp: Use helper to fix bug
+        (WebCore::SVGTextRunWalker::walk):
+
 2009-12-23  Kent Tamura  <tkent at chromium.org>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 88774cb..7d0e5a9 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -24,7 +24,6 @@
 #include "config.h"
 #include "Font.h"
 
-#include "CharacterNames.h"
 #include "FloatRect.h"
 #include "FontCache.h"
 #include "FontFallbackList.h"
@@ -266,6 +265,22 @@ FontSelector* Font::fontSelector() const
     return m_fontList ? m_fontList->fontSelector() : 0;
 }
 
+String Font::normalizeSpaces(const String& string)
+{
+    unsigned length = string.length();
+    Vector<UChar, 256> buffer(length);
+    bool didReplacement = false;
+
+    for (unsigned i = 0; i < length; ++i) {
+        UChar originalCharacter = string[i];
+        buffer[i] = normalizeSpaces(originalCharacter);
+        if (buffer[i] != originalCharacter)
+            didReplacement = true;
+    }
+
+    return didReplacement ? String(buffer.data(), length) : string;
+}
+
 static bool shouldUseFontSmoothing = true;
 
 void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
index fbb738a..ff93388 100644
--- a/WebCore/platform/graphics/Font.h
+++ b/WebCore/platform/graphics/Font.h
@@ -25,6 +25,7 @@
 #ifndef Font_h
 #define Font_h
 
+#include "CharacterNames.h"
 #include "TextRun.h"
 #include "FontDescription.h"
 #include "SimpleFontData.h"
@@ -176,6 +177,19 @@ public:
     static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; }
     static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; }
 
+    static inline UChar normalizeSpaces(UChar character)
+    {
+        if (treatAsSpace(character))
+            return space;
+
+        if (treatAsZeroWidthSpace(character))
+            return zeroWidthSpace;
+
+        return character;
+    }
+
+    static String normalizeSpaces(const String&);
+
 #if ENABLE(SVG_FONTS)
     bool isSVGFont() const;
     SVGFontElement* svgFont() const;
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index 5246593..dd945e5 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -135,13 +135,7 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
     UChar codeUnits[2];
     int codeUnitsLength;
     if (c <= 0xFFFF) {
-        UChar c16 = c;
-        if (Font::treatAsSpace(c16))
-            codeUnits[0] = ' ';
-        else if (Font::treatAsZeroWidthSpace(c16))
-            codeUnits[0] = zeroWidthSpace;
-        else
-            codeUnits[0] = c16;
+        codeUnits[0] = Font::normalizeSpaces(c);
         codeUnitsLength = 1;
     } else {
         codeUnits[0] = U16_LEAD(c);
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index 1e44626..0196ab2 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -44,24 +44,11 @@
 
 namespace WebCore {
 
-static const QString qstring(const TextRun& run)
+static const QString fromRawDataWithoutRef(const String& string)
 {
-    // We don't detach
-    return QString::fromRawData(reinterpret_cast<const QChar*>(run.characters()), run.length());
-}
-
-static const QString fixSpacing(const QString &string)
-{
-    //Only detach if we're actually changing something
-    QString possiblyDetached = string;
-    for (int i = 0; i < string.length(); ++i) {
-        const QChar c = string.at(i);
-        if (c.unicode() != 0x20 && Font::treatAsSpace(c.unicode()))
-            possiblyDetached[i] = 0x20; // detach
-        else if (c.unicode() != 0x200c && Font::treatAsZeroWidthSpace(c.unicode()))
-            possiblyDetached[i] = 0x200c; // detach
-    }
-    return possiblyDetached;
+    // We don't detach. This assumes the WebCore string data will stay valid for the
+    // lifetime of the QString we pass back, since we don't ref the WebCore string.
+    return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters()), string.length());
 }
 
 static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
@@ -110,7 +97,8 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
             p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness()));
     }
 
-    const QString string = fixSpacing(qstring(run));
+    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+    QString string = fromRawDataWithoutRef(sanitized);
 
     // text shadow
     IntSize shadowSize;
@@ -185,7 +173,10 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
 {
     if (!run.length())
         return 0;
-    const QString string = fixSpacing(qstring(run));
+
+    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+    QString string = fromRawDataWithoutRef(sanitized);
+
     QTextLayout layout(string, font());
     QTextLine line = setupLayout(&layout, run);
     int w = int(line.naturalTextWidth());
@@ -198,7 +189,9 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
 
 int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const
 {
-    const QString string = fixSpacing(qstring(run));
+    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+    QString string = fromRawDataWithoutRef(sanitized);
+
     QTextLayout layout(string, font());
     QTextLine line = setupLayout(&layout, run);
     return line.xToCursor(position);
@@ -206,7 +199,9 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool
 
 FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
 {
-    const QString string = fixSpacing(qstring(run));
+    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
+    QString string = fromRawDataWithoutRef(sanitized);
+
     QTextLayout layout(string, font());
     QTextLine line = setupLayout(&layout, run);
 
diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h
index cd09447..5cd5ea5 100644
--- a/WebCore/platform/text/CharacterNames.h
+++ b/WebCore/platform/text/CharacterNames.h
@@ -59,6 +59,7 @@ namespace WebCore {
     const UChar rightToLeftMark = 0x200F;
     const UChar rightToLeftOverride = 0x202E;
     const UChar softHyphen = 0x00AD;
+    const UChar space = 0x0020;
     const UChar whiteBullet = 0x25E6;
     const UChar zeroWidthSpace = 0x200B;
 
diff --git a/WebCore/svg/SVGFont.cpp b/WebCore/svg/SVGFont.cpp
index 7e3cec0..d978328 100644
--- a/WebCore/svg/SVGFont.cpp
+++ b/WebCore/svg/SVGFont.cpp
@@ -243,7 +243,8 @@ struct SVGTextRunWalker {
         // Should hold true for SVG text, otherwhise sth. is wrong
         ASSERT(to - from == run.length());
 
-        Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(String(run.data(from), run.length()), run.rtl()));
+        const String text = Font::normalizeSpaces(String(run.data(from), run.length()));
+        Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(text, run.rtl()));
 
         SVGGlyphIdentifier identifier;
         bool foundGlyph = false;
@@ -270,7 +271,8 @@ struct SVGTextRunWalker {
             // extended to the n-th next character (where n is 'characterLookupRange'), to check for any possible ligature.
             characterLookupRange = endOfScanRange - i;
 
-            String lookupString(run.data(i), characterLookupRange);
+            String lookupString = Font::normalizeSpaces(String(run.data(i), characterLookupRange));
+
             Vector<SVGGlyphIdentifier> glyphs;
             if (haveAltGlyph)
                 glyphs.append(altGlyphIdentifier);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list