OPENTYPE_VERTICAL support for Chromium Win
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Aug 2012 18:52:17 +0000 (18:52 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Aug 2012 18:52:17 +0000 (18:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=94822

Patch by Koji Ishii <kojiishi@gmail.com> on 2012-08-28
Reviewed by Tony Chang.

To fix bug 51450 - Glyphs in vertical text tests are rotated 90 degrees clockwise on Chromium Windows,
this patch adds support of OPENTYPE_VERTICAL feature for Chromium Windows.
Since enabling OPENTYPE_VERTICAL feature would require rather a big number of tests to rebaseline,
the actual fix is separated into this patch, and the feature will be enabled in bug 51450,
so that it is easier to revert on any perf regressions, as suggested by Tony in comment #50 of bug 51450.

All changes in this patch are behind #if ENABLE(OPENTYPE_VERTICAL) and therefore no tests are included in this patch.
All tests in fast/writing-modes currently skipped will be enabled in bug 51450.

* WebCore.gyp/WebCore.gyp: Added platform/graphics/opentype/OpenType*.
* WebCore.gypi: Ditto.
* platform/graphics/FontCache.h: SKia uses uint32_t as FontFileKey.
* platform/graphics/GlyphPageTreeNode.cpp:
(WebCore::fill): Replace vertical alternate glyphs if vertical flow.
* platform/graphics/SimpleFontData.cpp: Added m_verticalData.
(WebCore::SimpleFontData::SimpleFontData):
* platform/graphics/SimpleFontData.h:
(WebCore::SimpleFontData::verticalData):
(SimpleFontData):
(WebCore::SimpleFontData::widthForGlyph):
* platform/graphics/chromium/FontChromiumWin.cpp:
(WebCore::Font::drawGlyphs): Draw glyphs verticaly if font->verticalData().
* platform/graphics/chromium/FontPlatformDataChromiumWin.cpp:
(WebCore::FontPlatformData::verticalData): Added.
(WebCore):
(WebCore::FontPlatformData::openTypeTable): Added.
* platform/graphics/chromium/FontPlatformDataChromiumWin.h:
(WebCore):
(FontPlatformData): Added verticalData() and openTypeTable().

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@126907 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.gyp/WebCore.gyp
Source/WebCore/WebCore.gypi
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
Source/WebCore/platform/graphics/SimpleFontData.cpp
Source/WebCore/platform/graphics/SimpleFontData.h
Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h

index 9aea5a3..dd3c0cc 100644 (file)
@@ -1,3 +1,40 @@
+2012-08-28  Koji Ishii  <kojiishi@gmail.com>
+
+        OPENTYPE_VERTICAL support for Chromium Win
+        https://bugs.webkit.org/show_bug.cgi?id=94822
+
+        Reviewed by Tony Chang.
+
+        To fix bug 51450 - Glyphs in vertical text tests are rotated 90 degrees clockwise on Chromium Windows,
+        this patch adds support of OPENTYPE_VERTICAL feature for Chromium Windows.
+        Since enabling OPENTYPE_VERTICAL feature would require rather a big number of tests to rebaseline,
+        the actual fix is separated into this patch, and the feature will be enabled in bug 51450,
+        so that it is easier to revert on any perf regressions, as suggested by Tony in comment #50 of bug 51450.
+
+        All changes in this patch are behind #if ENABLE(OPENTYPE_VERTICAL) and therefore no tests are included in this patch.
+        All tests in fast/writing-modes currently skipped will be enabled in bug 51450.
+
+        * WebCore.gyp/WebCore.gyp: Added platform/graphics/opentype/OpenType*.
+        * WebCore.gypi: Ditto.
+        * platform/graphics/FontCache.h: SKia uses uint32_t as FontFileKey.
+        * platform/graphics/GlyphPageTreeNode.cpp:
+        (WebCore::fill): Replace vertical alternate glyphs if vertical flow.
+        * platform/graphics/SimpleFontData.cpp: Added m_verticalData.
+        (WebCore::SimpleFontData::SimpleFontData):
+        * platform/graphics/SimpleFontData.h:
+        (WebCore::SimpleFontData::verticalData):
+        (SimpleFontData):
+        (WebCore::SimpleFontData::widthForGlyph):
+        * platform/graphics/chromium/FontChromiumWin.cpp:
+        (WebCore::Font::drawGlyphs): Draw glyphs verticaly if font->verticalData().
+        * platform/graphics/chromium/FontPlatformDataChromiumWin.cpp:
+        (WebCore::FontPlatformData::verticalData): Added.
+        (WebCore):
+        (WebCore::FontPlatformData::openTypeTable): Added.
+        * platform/graphics/chromium/FontPlatformDataChromiumWin.h:
+        (WebCore):
+        (FontPlatformData): Added verticalData() and openTypeTable().
+
 2012-08-28  Andy Estes  <aestes@apple.com>
 
         Add header guards to WebTileCacheLayer.h.
index 48b7324..4082d85 100644 (file)
           'sources/': [
             ['exclude', 'Posix\\.cpp$'],
 
+            ['include', 'platform/graphics/opentype/OpenTypeTypes\\.h$'],
+            ['include', 'platform/graphics/opentype/OpenTypeVerticalData\\.cpp$'],
+            ['include', 'platform/graphics/opentype/OpenTypeVerticalData\\.h$'],
+
             # The Chromium Win currently uses GlyphPageTreeNodeChromiumWin.cpp from
             # platform/graphics/chromium, included by regex above, instead.
             ['exclude', 'platform/graphics/skia/FontCacheSkia\\.cpp$'],
index f669d62..5e72d43 100644 (file)
             'platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp',
             'platform/graphics/opentype/OpenTypeSanitizer.cpp',
             'platform/graphics/opentype/OpenTypeSanitizer.h',
+            'platform/graphics/opentype/OpenTypeTypes.h',
             'platform/graphics/opentype/OpenTypeUtilities.cpp',
             'platform/graphics/opentype/OpenTypeUtilities.h',
+            'platform/graphics/opentype/OpenTypeVerticalData.cpp',
+            'platform/graphics/opentype/OpenTypeVerticalData.h',
             'platform/graphics/openvg/EGLDisplayOpenVG.cpp',
             'platform/graphics/openvg/EGLDisplayOpenVG.h',
             'platform/graphics/openvg/EGLUtils.h',
index 858db21..21d090a 100644 (file)
@@ -106,7 +106,11 @@ public:
 #endif
 
 #if ENABLE(OPENTYPE_VERTICAL)
+#if USE(SKIA)
+    typedef uint32_t FontFileKey;
+#else
     typedef AtomicString FontFileKey;
+#endif
     OpenTypeVerticalData* getVerticalData(const FontFileKey&, const FontPlatformData&);
 #endif
 
index 87e93fd..a2f0d04 100644 (file)
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "GlyphPageTreeNode.h"
 
+#include "OpenTypeVerticalData.h"
 #include "PlatformString.h"
 #include "SegmentedFontData.h"
 #include "SimpleFontData.h"
@@ -130,7 +131,12 @@ static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar*
     if (SimpleFontData::AdditionalFontData* additionalFontData = fontData->fontData())
         return additionalFontData->fillSVGGlyphPage(pageToFill, offset, length, buffer, bufferLength, fontData);
 #endif
-    return pageToFill->fill(offset, length, buffer, bufferLength, fontData);
+    bool hasGlyphs = pageToFill->fill(offset, length, buffer, bufferLength, fontData);
+#if ENABLE(OPENTYPE_VERTICAL)
+    if (hasGlyphs && fontData->verticalData())
+        fontData->verticalData()->substituteWithVerticalGlyphs(fontData, pageToFill, offset, length);
+#endif
+    return hasGlyphs;
 }
 
 void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber)
index 1232e47..eae95bd 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "Font.h"
 #include "FontCache.h"
+#include "OpenTypeVerticalData.h"
 
 #include <wtf/MathExtras.h>
 #include <wtf/UnusedParam.h>
@@ -49,11 +50,20 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust
     , m_isLoading(isLoading)
     , m_isTextOrientationFallback(isTextOrientationFallback)
     , m_isBrokenIdeographFallback(false)
+#if ENABLE(OPENTYPE_VERTICAL)
+    , m_verticalData(0)
+#endif
     , m_hasVerticalGlyphs(false)
 {
     platformInit();
     platformGlyphInit();
     platformCharWidthInit();
+#if ENABLE(OPENTYPE_VERTICAL)
+    if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
+        m_verticalData = platformData.verticalData();
+        m_hasVerticalGlyphs = m_verticalData && m_verticalData->hasVerticalMetrics();
+    }
+#endif
 }
 
 SimpleFontData::SimpleFontData(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
@@ -64,6 +74,9 @@ SimpleFontData::SimpleFontData(PassOwnPtr<AdditionalFontData> fontData, float fo
     , m_isLoading(false)
     , m_isTextOrientationFallback(false)
     , m_isBrokenIdeographFallback(false)
+#if ENABLE(OPENTYPE_VERTICAL)
+    , m_verticalData(0)
+#endif
     , m_hasVerticalGlyphs(false)
 {
     m_fontData->initializeFontData(this, fontSize);
index 820c265..c4d3b96 100644 (file)
@@ -88,7 +88,7 @@ public:
 
     const FontPlatformData& platformData() const { return m_platformData; }
 #if ENABLE(OPENTYPE_VERTICAL)
-    const OpenTypeVerticalData* verticalData() const { return 0; } // FIXME: implement
+    const OpenTypeVerticalData* verticalData() const { return m_verticalData; }
 #endif
 
     SimpleFontData* smallCapsFontData(const FontDescription&) const;
@@ -229,6 +229,9 @@ private:
 
     mutable OwnPtr<GlyphMetricsMap<FloatRect> > m_glyphToBoundsMap;
     mutable GlyphMetricsMap<float> m_glyphToWidthMap;
+#if ENABLE(OPENTYPE_VERTICAL)
+    const OpenTypeVerticalData* m_verticalData;
+#endif
 
     bool m_treatAsFixedPitch;
     bool m_isCustomFont;  // Whether or not we are custom font loaded via @font-face
@@ -317,6 +320,14 @@ ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
 
     if (m_fontData)
         width = m_fontData->widthForSVGGlyph(glyph, m_platformData.size());
+#if ENABLE(OPENTYPE_VERTICAL)
+    else if (m_verticalData)
+#if USE(CG) || USE(CAIRO) || PLATFORM(WX) || USE(SKIA_ON_MAC_CHROMIUM)
+        width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
+#else
+        width = m_verticalData->advanceHeight(this, glyph);
+#endif
+#endif
     else
         width = platformWidthForGlyph(glyph);
 
index 3d30e18..afd08db 100644 (file)
@@ -390,15 +390,56 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
     // We draw the glyphs in chunks to avoid having to do a heap allocation for
     // the arrays of characters and advances.
     const int kMaxBufferLength = 256;
-    Vector<WORD, kMaxBufferLength> glyphs;
     Vector<int, kMaxBufferLength> advances;
     int glyphIndex = 0;  // The starting glyph of the current chunk.
 
+    float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
+#if ENABLE(OPENTYPE_VERTICAL)
+    const OpenTypeVerticalData* verticalData = font->verticalData();
+    if (verticalData) {
+        Vector<FloatPoint, kMaxBufferLength> translations;
+        Vector<GOFFSET, kMaxBufferLength> offsets;
+
+        // Skia doesn't have matrix for glyph coordinate space, so we rotate back the CTM.
+        AffineTransform savedMatrix = graphicsContext->getCTM();
+        graphicsContext->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
+        graphicsContext->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
+
+        const FontMetrics& metrics = font->fontMetrics();
+        SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline));
+        while (glyphIndex < numGlyphs) {
+            // How many chars will be in this chunk?
+            int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
+
+            const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
+            translations.resize(curLen);
+            verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], curLen, reinterpret_cast<float*>(&translations[0]));
+            // To position glyphs vertically, we use offsets instead of advances.
+            advances.resize(curLen);
+            advances.fill(0);
+            offsets.resize(curLen);
+            float currentWidth = 0;
+            for (int i = 0; i < curLen; ++i, ++glyphIndex) {
+                offsets[i].du = lroundf(translations[i].x());
+                offsets[i].dv = -lroundf(currentWidth - translations[i].y());
+                currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
+            }
+            SkPoint origin;
+            origin.set(verticalOriginX, SkFloatToScalar(point.y() + horizontalOffset - point.x()));
+            horizontalOffset += currentWidth;
+            paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], &offsets[0], &origin);
+        }
+
+        graphicsContext->setCTM(savedMatrix);
+        return;
+    }
+#endif
+
     // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
     // of each glyph in floating point units and rounds to integer advances at the last possible moment.
 
-    float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
     int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
+    Vector<WORD, kMaxBufferLength> glyphs;
     while (glyphIndex < numGlyphs) {
         // How many chars will be in this chunk?
         int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
index 6f27f8a..183ad0b 100644 (file)
@@ -191,6 +191,31 @@ SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
     return m_scriptFontProperties;
 }
 
+#if ENABLE(OPENTYPE_VERTICAL)
+const OpenTypeVerticalData* FontPlatformData::verticalData() const
+{
+    SkFontID id = typeface()->uniqueID();
+    return fontCache()->getVerticalData(id, *this);
+}
+
+PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
+{
+    HWndDC hdc(0);
+    HGDIOBJ oldFont = SelectObject(hdc, hfont());
+
+    DWORD size = GetFontData(hdc, table, 0, 0, 0);
+    RefPtr<SharedBuffer> buffer;
+    if (size != GDI_ERROR) {
+        buffer = SharedBuffer::create(size);
+        DWORD result = GetFontData(hdc, table, 0, (PVOID)buffer->data(), size);
+        ASSERT(result == size);
+    }
+
+    SelectObject(hdc, oldFont);
+    return buffer.release();
+}
+#endif
+
 #ifndef NDEBUG
 String FontPlatformData::description() const
 {
index 55a5c2b..b5ebef2 100644 (file)
@@ -35,6 +35,7 @@
 #include "config.h"
 
 #include "FontOrientation.h"
+#include "SharedBuffer.h"
 #include "SkTypeface.h"
 #include <wtf/Forward.h>
 #include <wtf/PassRefPtr.h>
@@ -53,6 +54,9 @@ namespace WebCore {
 SkTypeface* CreateTypefaceFromHFont(HFONT, int* size, int* lfQuality);
 
 class FontDescription;
+#if ENABLE(OPENTYPE_VERTICAL)
+class OpenTypeVerticalData;
+#endif
 
 class FontPlatformData {
 public:
@@ -92,6 +96,11 @@ public:
         return m_font == other.m_font && m_size == other.m_size && m_orientation == other.m_orientation;
     }
 
+#if ENABLE(OPENTYPE_VERTICAL)
+    const OpenTypeVerticalData* verticalData() const;
+    PassRefPtr<SharedBuffer> openTypeTable(uint32_t table) const;
+#endif
+
 #ifndef NDEBUG
     String description() const;
 #endif