Title: [194839] trunk
Revision
194839
Author
mmaxfi...@apple.com
Date
2016-01-10 21:55:14 -0800 (Sun, 10 Jan 2016)

Log Message

[SVG -> OTF Converter] Parsing failures cause use of incomplete fonts
https://bugs.webkit.org/show_bug.cgi?id=152772
<rdar://problem/24043104>

Reviewed by Simon Fraser.

Source/WebCore:

Originally, if we fail to parse a glyph, we would simply skip the glyph. However, this means that
we will create an incomplete font without all the necessary glyphs. This causes very distressing
text where all the occurances of a particular letter are missing. Instead, we should treat the
entire font as invalid.

Test: fast/text/svg-font-invalid-glyph-path-failure.html

* css/CSSFontFaceSource.cpp:
(WebCore::CSSFontFaceSource::font):
* loader/cache/CachedSVGFont.cpp:
(WebCore::CachedSVGFont::ensureCustomFontData):
* svg/SVGToOTFFontConversion.cpp:
(WebCore::SVGToOTFFontConverter::error):
(WebCore::SVGToOTFFontConverter::transcodeGlyphPaths):
(WebCore::SVGToOTFFontConverter::processGlyphElement):
(WebCore::convertSVGToOTFFont):
* svg/SVGToOTFFontConversion.h:

LayoutTests:

Make sure the font renders as if its invalid.

* fast/text/resources/bustedfont.svg: Added.
* fast/text/svg-font-invalid-glyph-path-failure-expected.html: Added.
* fast/text/svg-font-invalid-glyph-path-failure.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (194838 => 194839)


--- trunk/LayoutTests/ChangeLog	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/LayoutTests/ChangeLog	2016-01-11 05:55:14 UTC (rev 194839)
@@ -1,3 +1,17 @@
+2016-01-10  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [SVG -> OTF Converter] Parsing failures cause use of incomplete fonts
+        https://bugs.webkit.org/show_bug.cgi?id=152772
+        <rdar://problem/24043104>
+
+        Reviewed by Simon Fraser.
+
+        Make sure the font renders as if its invalid.
+
+        * fast/text/resources/bustedfont.svg: Added.
+        * fast/text/svg-font-invalid-glyph-path-failure-expected.html: Added.
+        * fast/text/svg-font-invalid-glyph-path-failure.html: Added.
+
 2016-01-10  Yusuke Suzuki  <utatane....@gmail.com>
 
         [JSC] Iterating over a Set/Map is too slow

Added: trunk/LayoutTests/fast/text/resources/bustedfont.svg (0 => 194839)


--- trunk/LayoutTests/fast/text/resources/bustedfont.svg	                        (rev 0)
+++ trunk/LayoutTests/fast/text/resources/bustedfont.svg	2016-01-11 05:55:14 UTC (rev 194839)
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="Litherum" horiz-adv-x="1024">
+<font-face units-per-em="14" ascent="14" descent="0"/>
+<glyph unicode="a" horiz-adv-x="14" d="M0 0v14h14v-14z"/>
+<glyph unicode="e" horiz-adv-x="14" d="M0 0v14D14v-14z"/>
+<glyph unicode="i" horiz-adv-x="14" d="M0 0v14h14v-14z"/>
+<glyph unicode="o" horiz-adv-x="14" d="M0 0v14h14v-14z"/>
+<glyph unicode="u" horiz-adv-x="14" d="M0 0v14h14v-14z"/>
+</font>
+</defs>
+</svg>

Added: trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure-expected.html (0 => 194839)


--- trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure-expected.html	2016-01-11 05:55:14 UTC (rev 194839)
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+This test makes sure that a path parsing failure of (a single glyph of) an SVG font is treated as an invalid font. There should be text below (instead of a big black box).
+<div style="font: 50px Avenir">aeiou</div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure.html (0 => 194839)


--- trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/svg-font-invalid-glyph-path-failure.html	2016-01-11 05:55:14 UTC (rev 194839)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "bustedfont";
+    src: url("resources/bustedfont.svg") format("svg");
+}
+</style>
+</head>
+<body>
+This test makes sure that a path parsing failure of (a single glyph of) an SVG font is treated as an invalid font. There should be text below (instead of a big black box).
+<div style="font: 50px bustedfont, Avenir">aeiou</div>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (194838 => 194839)


--- trunk/Source/WebCore/ChangeLog	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/Source/WebCore/ChangeLog	2016-01-11 05:55:14 UTC (rev 194839)
@@ -1,3 +1,29 @@
+2016-01-10  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [SVG -> OTF Converter] Parsing failures cause use of incomplete fonts
+        https://bugs.webkit.org/show_bug.cgi?id=152772
+        <rdar://problem/24043104>
+
+        Reviewed by Simon Fraser.
+
+        Originally, if we fail to parse a glyph, we would simply skip the glyph. However, this means that
+        we will create an incomplete font without all the necessary glyphs. This causes very distressing
+        text where all the occurances of a particular letter are missing. Instead, we should treat the
+        entire font as invalid.
+
+        Test: fast/text/svg-font-invalid-glyph-path-failure.html
+
+        * css/CSSFontFaceSource.cpp:
+        (WebCore::CSSFontFaceSource::font):
+        * loader/cache/CachedSVGFont.cpp:
+        (WebCore::CachedSVGFont::ensureCustomFontData):
+        * svg/SVGToOTFFontConversion.cpp:
+        (WebCore::SVGToOTFFontConverter::error):
+        (WebCore::SVGToOTFFontConverter::transcodeGlyphPaths):
+        (WebCore::SVGToOTFFontConverter::processGlyphElement):
+        (WebCore::convertSVGToOTFFont):
+        * svg/SVGToOTFFontConversion.h:
+
 2016-01-10  Andreas Kling  <akl...@apple.com>
 
         Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL cont'd

Modified: trunk/Source/WebCore/css/CSSFontFaceSource.cpp (194838 => 194839)


--- trunk/Source/WebCore/css/CSSFontFaceSource.cpp	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/Source/WebCore/css/CSSFontFaceSource.cpp	2016-01-11 05:55:14 UTC (rev 194839)
@@ -144,8 +144,8 @@
                 SVGFontElement& fontElement = downcast<SVGFontElement>(*m_svgFontFaceElement->parentNode());
                 // FIXME: Re-run this when script modifies the element or any of its descendents
                 // FIXME: We might have already converted this font. Make existing conversions discoverable.
-                Vector<char> otfFont = convertSVGToOTFFont(fontElement);
-                m_generatedOTFBuffer = SharedBuffer::adoptVector(otfFont);
+                if (auto otfFont = convertSVGToOTFFont(fontElement))
+                    m_generatedOTFBuffer = SharedBuffer::adoptVector(otfFont.value());
                 if (!m_generatedOTFBuffer)
                     return nullptr;
                 auto customPlatformData = createFontCustomPlatformData(*m_generatedOTFBuffer);

Modified: trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp (194838 => 194839)


--- trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp	2016-01-11 05:55:14 UTC (rev 194839)
@@ -92,8 +92,12 @@
             maybeInitializeExternalSVGFontElement(remoteURI);
         if (!m_externalSVGFontElement)
             return false;
-        Vector<char> convertedFont = convertSVGToOTFFont(*m_externalSVGFontElement);
-        m_convertedFont = SharedBuffer::adoptVector(convertedFont);
+        if (auto convertedFont = convertSVGToOTFFont(*m_externalSVGFontElement))
+            m_convertedFont = SharedBuffer::adoptVector(convertedFont.value());
+        else {
+            m_externalSVGDocument = nullptr;
+            return false;
+        }
 #endif
     }
 

Modified: trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp (194838 => 194839)


--- trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/Source/WebCore/svg/SVGToOTFFontConversion.cpp	2016-01-11 05:55:14 UTC (rev 194839)
@@ -51,13 +51,18 @@
 class SVGToOTFFontConverter {
 public:
     SVGToOTFFontConverter(const SVGFontElement&);
-    void convertSVGToOTFFont();
+    bool convertSVGToOTFFont();
 
     Vector<char> releaseResult()
     {
         return WTFMove(m_result);
     }
 
+    bool error() const
+    {
+        return m_error;
+    }
+
 private:
     struct GlyphData {
         GlyphData(Vector<char>&& charString, const SVGGlyphElement* glyphElement, float horizontalAdvance, float verticalAdvance, FloatRect boundingBox, const String& codepoints)
@@ -257,6 +262,7 @@
     unsigned m_tablesAppendedCount;
     char m_weight;
     bool m_italic;
+    bool m_error { false };
 };
 
 static uint16_t roundDownToPowerOfTwo(uint16_t x)
@@ -1269,7 +1275,7 @@
 
     ok = SVGPathParser::parse(source, builder);
     if (!ok)
-        result.clear();
+        return { };
 
     boundingBox = builder.boundingBox();
 
@@ -1291,6 +1297,10 @@
 
     Optional<FloatRect> glyphBoundingBox;
     auto path = transcodeGlyphPaths(horizontalAdvance, glyphOrMissingGlyphElement, glyphBoundingBox);
+    if (!path.size()) {
+        // It's better to use a fallback font rather than use a font without all its glyphs.
+        m_error = true;
+    }
     if (!boundingBox)
         boundingBox = glyphBoundingBox;
     else if (glyphBoundingBox)
@@ -1521,10 +1531,10 @@
     ++m_tablesAppendedCount;
 }
 
-void SVGToOTFFontConverter::convertSVGToOTFFont()
+bool SVGToOTFFontConverter::convertSVGToOTFFont()
 {
     if (m_glyphs.isEmpty())
-        return;
+        return false;
 
     uint16_t numTables = 14;
     uint16_t roundedNumTables = roundDownToPowerOfTwo(numTables);
@@ -1566,12 +1576,16 @@
     // checksumAdjustment: "To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory,
     // sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will now be wrong. That is OK."
     overwrite32(headTableOffset + 8, 0xB1B0AFBAU - calculateChecksum(0, m_result.size()));
+    return true;
 }
 
-Vector<char> convertSVGToOTFFont(const SVGFontElement& element)
+Optional<Vector<char>> convertSVGToOTFFont(const SVGFontElement& element)
 {
     SVGToOTFFontConverter converter(element);
-    converter.convertSVGToOTFFont();
+    if (converter.error())
+        return Nullopt;
+    if (!converter.convertSVGToOTFFont())
+        return Nullopt;
     return converter.releaseResult();
 }
 

Modified: trunk/Source/WebCore/svg/SVGToOTFFontConversion.h (194838 => 194839)


--- trunk/Source/WebCore/svg/SVGToOTFFontConversion.h	2016-01-11 05:54:03 UTC (rev 194838)
+++ trunk/Source/WebCore/svg/SVGToOTFFontConversion.h	2016-01-11 05:55:14 UTC (rev 194839)
@@ -26,13 +26,14 @@
 #ifndef SVGToOTFFontConversion_h
 #define SVGToOTFFontConversion_h
 
+#include <wtf/Optional.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
 class SVGFontElement;
 
-Vector<char> convertSVGToOTFFont(const SVGFontElement&);
+Optional<Vector<char>> convertSVGToOTFFont(const SVGFontElement&);
 
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to