Log Message
re-add support for GDI text behind a compile flag https://bugs.webkit.org/show_bug.cgi?id=69530
Reviewed by James Robinson. Source/WebCore: Reverts back to using GDI for text (when possible) but keeps skia-text version behind a compile-flag. If/when we can resolve the outstanding soft-clip and intl-performance bugs with the skia version, we may change the compile-flag to reenable skia. Previous change http://trac.webkit.org/changeset/94589 removed the GDI code. * platform/graphics/chromium/FontChromiumWin.cpp: (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::TransparencyAwareFontPainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::init): (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::initializeForGDI): (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::~TransparencyAwareFontPainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::estimateTextBounds): (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::drawGlyphs): (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::hdc): (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter): (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::estimateTextBounds): (WebCore::drawGlyphsWin): (WebCore::Font::drawGlyphs): (WebCore::Font::drawComplexText): * platform/graphics/chromium/UniscribeHelper.cpp: (WebCore::UniscribeHelper::draw): * platform/graphics/skia/PlatformContextSkia.cpp: (WebCore::PlatformContextSkia::isNativeFontRenderingAllowed): * platform/graphics/skia/PlatformContextSkia.h: * platform/graphics/skia/SkiaFontWin.cpp: (WebCore::windowsCanHandleDrawTextShadow): (WebCore::windowsCanHandleTextDrawing): (WebCore::windowsCanHandleTextDrawingWithoutShadow): * platform/graphics/skia/SkiaFontWin.h: Source/WebKit/chromium: * features.gypi: LayoutTests: * platform/chromium/test_expectations.txt:
Modified Paths
- trunk/LayoutTests/ChangeLog
- trunk/LayoutTests/platform/chromium/test_expectations.txt
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
- trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
- trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
- trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
- trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
- trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.h
- trunk/Source/WebKit/chromium/ChangeLog
- trunk/Source/WebKit/chromium/features.gypi
Diff
Modified: trunk/LayoutTests/ChangeLog (97148 => 97149)
--- trunk/LayoutTests/ChangeLog 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/LayoutTests/ChangeLog 2011-10-11 13:11:33 UTC (rev 97149)
@@ -1,3 +1,12 @@
+2011-10-11 Mike Reed <r...@google.com>
+
+ re-add support for GDI text behind a compile flag
+ https://bugs.webkit.org/show_bug.cgi?id=69530
+
+ Reviewed by James Robinson.
+
+ * platform/chromium/test_expectations.txt:
+
2011-10-11 Jer Noble <jer.no...@apple.com>
REGRESSION (r96770-r96777): fast/dom/Window/window-properties.html, fast/dom/prototype-inheritance-2.html, fast/js/global-constructors.html failing on SnowLeopard Intel Release (Tests)
Modified: trunk/LayoutTests/platform/chromium/test_expectations.txt (97148 => 97149)
--- trunk/LayoutTests/platform/chromium/test_expectations.txt 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/LayoutTests/platform/chromium/test_expectations.txt 2011-10-11 13:11:33 UTC (rev 97149)
@@ -1415,6 +1415,14 @@
// This test also started failing with the merge of March 25th 2009
BUGCR10441 MAC WIN : transitions/transition-end-event-transform.html = PASS TEXT
+// Disable these while we're back to using GDI for text drawing. These give slightly
+// different results than with Skia. When we switch back to Skia, we can
+// reenable these.
+BUGCR99500 WIN : media/audio-repaint.html = IMAGE
+BUGCR99500 WIN : svg/as-background-image/animated-svg-as-background.html = IMAGE
+BUGCR99500 WIN : svg/batik/text/textStyles.svg = IMAGE
+BUGCR99500 WIN : svg/custom/simple-text-double-shadow.svg = IMAGE
+
// Merge 41768:41807
// Perhaps just needs new baseline?
// These tests were rebaselined with failure long ago. We shouldn't do this, and
@@ -2104,7 +2112,6 @@
// On XP, some glyphs show subpixel antialiasing when they shouldn't
BUGWK65203 XP : fast/text/international/bidi-mirror-he-ar.html = IMAGE
-BUGWK65203 XP : svg/batik/text/textStyles.svg = IMAGE
BUGWK42428 LINUX WIN : svg/W3C-SVG-1.1/filters-conv-01-f.svg = IMAGE+TEXT
Modified: trunk/Source/WebCore/ChangeLog (97148 => 97149)
--- trunk/Source/WebCore/ChangeLog 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/ChangeLog 2011-10-11 13:11:33 UTC (rev 97149)
@@ -1,3 +1,44 @@
+2011-10-11 Mike Reed <r...@google.com>
+
+ re-add support for GDI text behind a compile flag
+ https://bugs.webkit.org/show_bug.cgi?id=69530
+
+ Reviewed by James Robinson.
+
+ Reverts back to using GDI for text (when possible)
+ but keeps skia-text version behind a compile-flag. If/when we can
+ resolve the outstanding soft-clip and intl-performance bugs with the
+ skia version, we may change the compile-flag to reenable skia.
+
+ Previous change http://trac.webkit.org/changeset/94589 removed the GDI code.
+
+ * platform/graphics/chromium/FontChromiumWin.cpp:
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::TransparencyAwareFontPainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::init):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::initializeForGDI):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareFontPainter::~TransparencyAwareFontPainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::estimateTextBounds):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareGlyphPainter::drawGlyphs):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::hdc):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter):
+ (WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::estimateTextBounds):
+ (WebCore::drawGlyphsWin):
+ (WebCore::Font::drawGlyphs):
+ (WebCore::Font::drawComplexText):
+ * platform/graphics/chromium/UniscribeHelper.cpp:
+ (WebCore::UniscribeHelper::draw):
+ * platform/graphics/skia/PlatformContextSkia.cpp:
+ (WebCore::PlatformContextSkia::isNativeFontRenderingAllowed):
+ * platform/graphics/skia/PlatformContextSkia.h:
+ * platform/graphics/skia/SkiaFontWin.cpp:
+ (WebCore::windowsCanHandleDrawTextShadow):
+ (WebCore::windowsCanHandleTextDrawing):
+ (WebCore::windowsCanHandleTextDrawingWithoutShadow):
+ * platform/graphics/skia/SkiaFontWin.h:
+
2011-10-11 Tor Arne Vestbø <tor.arne.ves...@nokia.com>
[Qt] Remove all references to QTDIR_build and standalone_package
Modified: trunk/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp 2011-10-11 13:11:33 UTC (rev 97149)
@@ -41,10 +41,335 @@
#include "SkiaFontWin.h"
#include "UniscribeHelperTextRun.h"
+#if !ENABLE(SKIA_TEXT)
+#include "TransparencyWin.h"
+#include "skia/ext/skia_utils_win.h"
+#endif
+
#include <windows.h>
+using namespace std;
+
namespace WebCore {
+#if !ENABLE(SKIA_TEXT)
+namespace {
+
+bool canvasHasMultipleLayers(const SkCanvas* canvas)
+{
+ SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
+ iter.next(); // There is always at least one layer.
+ return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
+}
+
+class TransparencyAwareFontPainter {
+public:
+ TransparencyAwareFontPainter(GraphicsContext*, const FloatPoint&);
+ ~TransparencyAwareFontPainter();
+
+protected:
+ // Called by our subclass' constructor to initialize GDI if necessary. This
+ // is a separate function so it can be called after the subclass finishes
+ // construction (it calls virtual functions).
+ void init();
+
+ virtual IntRect estimateTextBounds() = 0;
+
+ // Use the context from the transparency helper when drawing with GDI. It
+ // may point to a temporary one.
+ GraphicsContext* m_graphicsContext;
+ PlatformGraphicsContext* m_platformContext;
+
+ FloatPoint m_point;
+
+ // Set when Windows can handle the type of drawing we're doing.
+ bool m_useGDI;
+
+ // These members are valid only when m_useGDI is set.
+ HDC m_hdc;
+ TransparencyWin m_transparency;
+
+private:
+ // Call when we're using GDI mode to initialize the TransparencyWin to help
+ // us draw GDI text.
+ void initializeForGDI();
+
+ bool m_createdTransparencyLayer; // We created a layer to give the font some alpha.
+};
+
+TransparencyAwareFontPainter::TransparencyAwareFontPainter(GraphicsContext* context,
+ const FloatPoint& point)
+ : m_graphicsContext(context)
+ , m_platformContext(context->platformContext())
+ , m_point(point)
+ , m_useGDI(windowsCanHandleTextDrawing(context))
+ , m_hdc(0)
+ , m_createdTransparencyLayer(false)
+{
+}
+
+void TransparencyAwareFontPainter::init()
+{
+ if (m_useGDI)
+ initializeForGDI();
+}
+
+void TransparencyAwareFontPainter::initializeForGDI()
+{
+ m_graphicsContext->save();
+ SkColor color = m_platformContext->effectiveFillColor();
+ // Used only when m_createdTransparencyLayer is true.
+ float layerAlpha = 0.0f;
+ if (SkColorGetA(color) != 0xFF) {
+ // When the font has some transparency, apply it by creating a new
+ // transparency layer with that opacity applied. We'll actually create
+ // a new transparency layer after we calculate the bounding box.
+ m_createdTransparencyLayer = true;
+ layerAlpha = SkColorGetA(color) / 255.0f;
+ // The color should be opaque now.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ }
+
+ TransparencyWin::LayerMode layerMode;
+ IntRect layerRect;
+ if (m_platformContext->isDrawingToImageBuffer()) {
+ // Assume if we're drawing to an image buffer that the background
+ // is not opaque and we have to undo ClearType. We may want to
+ // enhance this to actually check, since it will often be opaque
+ // and we could do ClearType in that case.
+ layerMode = TransparencyWin::TextComposite;
+ layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
+
+ // The transparency helper requires that we draw text in black in
+ // this mode and it will apply the color.
+ m_transparency.setTextCompositeColor(color);
+ color = SkColorSetRGB(0, 0, 0);
+ } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
+ // When we're drawing a web page, we know the background is opaque,
+ // but if we're drawing to a layer, we still need extra work.
+ layerMode = TransparencyWin::OpaqueCompositeLayer;
+ layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
+ } else {
+ // Common case of drawing onto the bottom layer of a web page: we
+ // know everything is opaque so don't need to do anything special.
+ layerMode = TransparencyWin::NoLayer;
+ }
+
+ // Bug 26088 - init() might fail if layerRect is invalid. Given this, we
+ // need to be careful to check for null pointers everywhere after this call
+ m_transparency.init(m_graphicsContext, layerMode,
+ TransparencyWin::KeepTransform, layerRect);
+
+ // Set up the DC, using the one from the transparency helper.
+ if (m_transparency.platformContext()) {
+ m_hdc = skia::BeginPlatformPaint(m_transparency.platformContext()->canvas());
+ SetTextColor(m_hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(m_hdc, TRANSPARENT);
+ }
+}
+
+TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
+{
+ if (!m_useGDI || !m_graphicsContext || !m_platformContext)
+ return;
+ m_transparency.composite();
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->endTransparencyLayer();
+ m_graphicsContext->restore();
+ if (m_transparency.platformContext())
+ skia::EndPlatformPaint(m_transparency.platformContext()->canvas());
+}
+
+// Specialization for simple GlyphBuffer painting.
+class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
+ public:
+ TransparencyAwareGlyphPainter(GraphicsContext*,
+ const SimpleFontData*,
+ const GlyphBuffer&,
+ int from, int numGlyphs,
+ const FloatPoint&);
+ ~TransparencyAwareGlyphPainter();
+
+ // Draws the partial string of glyphs, starting at |startAdvance| to the
+ // left of m_point. We express it this way so that if we're using the Skia
+ // drawing path we can use floating-point positioning, even though we have
+ // to use integer positioning in the GDI path.
+ bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const;
+
+ private:
+ virtual IntRect estimateTextBounds();
+
+ const SimpleFontData* m_font;
+ const GlyphBuffer& m_glyphBuffer;
+ int m_from;
+ int m_numGlyphs;
+
+ // When m_useGdi is set, this stores the previous HFONT selected into the
+ // m_hdc so we can restore it.
+ HGDIOBJ m_oldFont; // For restoring the DC to its original state.
+};
+
+TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter(
+ GraphicsContext* context,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs,
+ const FloatPoint& point)
+ : TransparencyAwareFontPainter(context, point)
+ , m_font(font)
+ , m_glyphBuffer(glyphBuffer)
+ , m_from(from)
+ , m_numGlyphs(numGlyphs)
+ , m_oldFont(0)
+{
+ init();
+
+ if (m_hdc)
+ m_oldFont = ::SelectObject(m_hdc, m_font->platformData().hfont());
+}
+
+TransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter()
+{
+ if (m_useGDI && m_hdc)
+ ::SelectObject(m_hdc, m_oldFont);
+}
+
+
+// Estimates the bounding box of the given text. This is copied from
+// FontCGWin.cpp, it is possible, but a lot more work, to get the precide
+// bounds.
+IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
+{
+ int totalWidth = 0;
+ for (int i = 0; i < m_numGlyphs; i++)
+ totalWidth += lroundf(m_glyphBuffer.advanceAt(m_from + i));
+
+ const FontMetrics& fontMetrics = m_font->fontMetrics();
+ return IntRect(m_point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
+ m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
+ totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
+ fontMetrics.lineSpacing());
+}
+
+bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
+ const WORD* glyphs,
+ const int* advances,
+ float startAdvance) const
+{
+ if (!m_useGDI) {
+ SkPoint origin = m_point;
+ origin.fX += SkFloatToScalar(startAdvance);
+ paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
+ numGlyphs, glyphs, advances, 0, &origin);
+ return true;
+ }
+
+ if (!m_graphicsContext || !m_hdc)
+ return true;
+
+ // Windows' origin is the top-left of the bounding box, so we have
+ // to subtract off the font ascent to get it.
+ int x = lroundf(m_point.x() + startAdvance);
+ int y = lroundf(m_point.y() - m_font->fontMetrics().ascent());
+
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
+ // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
+ // will have already returned true during the ctor initiatization of m_useGDI
+ ASSERT(shadowColor.alpha() == 255);
+ ASSERT(m_graphicsContext->fillColor().alpha() == 255);
+ ASSERT(!shadowBlur);
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(m_hdc);
+ SetTextColor(m_hdc, textColor);
+ ExtTextOut(m_hdc, x + shadowOffset.width(), y + shadowOffset.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
+ SetTextColor(m_hdc, savedTextColor);
+ }
+
+ return !!ExtTextOut(m_hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
+}
+
+class TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
+ public:
+ TransparencyAwareUniscribePainter(GraphicsContext*,
+ const Font*,
+ const TextRun&,
+ int from, int to,
+ const FloatPoint&);
+ ~TransparencyAwareUniscribePainter();
+
+ // Uniscibe will draw directly into our buffer, so we need to expose our DC.
+ HDC hdc() const { return m_hdc; }
+
+ private:
+ virtual IntRect estimateTextBounds();
+
+ const Font* m_font;
+ const TextRun& m_run;
+ int m_from;
+ int m_to;
+};
+
+TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter(
+ GraphicsContext* context,
+ const Font* font,
+ const TextRun& run,
+ int from, int to,
+ const FloatPoint& point)
+ : TransparencyAwareFontPainter(context, point)
+ , m_font(font)
+ , m_run(run)
+ , m_from(from)
+ , m_to(to)
+{
+ init();
+}
+
+TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter()
+{
+}
+
+IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
+{
+ // This case really really sucks. There is no convenient way to estimate
+ // the bounding box. So we run Uniscribe twice. If we find this happens a
+ // lot, the way to fix it is to make the extra layer after the
+ // UniscribeHelper has measured the text.
+ IntPoint intPoint(lroundf(m_point.x()),
+ lroundf(m_point.y()));
+
+ UniscribeHelperTextRun state(m_run, *m_font);
+ int left = lroundf(m_point.x()) + state.characterToX(m_from);
+ int right = lroundf(m_point.x()) + state.characterToX(m_to);
+
+ // Adjust for RTL script since we just want to know the text bounds.
+ if (left > right)
+ std::swap(left, right);
+
+ // This algorithm for estimating how much extra space we need (the text may
+ // go outside the selection rect) is based roughly on
+ // TransparencyAwareGlyphPainter::estimateTextBounds above.
+ const FontMetrics& fontMetrics = m_font->fontMetrics();
+ return IntRect(left - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
+ m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
+ (right - left) + fontMetrics.ascent() + fontMetrics.descent(),
+ fontMetrics.lineSpacing());
+}
+
+} // namespace
+#endif
+
bool Font::canReturnFallbackFontsForComplexText()
{
return false;
@@ -55,6 +380,7 @@
return false;
}
+#if ENABLE(SKIA_TEXT)
void Font::drawGlyphs(GraphicsContext* graphicsContext,
const SimpleFontData* font,
const GlyphBuffer& glyphBuffer,
@@ -113,7 +439,107 @@
paintSkiaText(graphicsContext, hfont, curLen, &glyphs[0], &advances[0], 0, &origin);
}
}
+#else
+static void drawGlyphsWin(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) {
+ TransparencyAwareGlyphPainter painter(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ // We draw the glyphs in chunks to avoid having to do a heap allocation for
+ // the arrays of characters and advances. Since ExtTextOut is the
+ // lowest-level text output function on Windows, there should be little
+ // penalty for splitting up the text. On the other hand, the buffer cannot
+ // be bigger than 4094 or the function will fail.
+ const int kMaxBufferLength = 256;
+ Vector<WORD, kMaxBufferLength> glyphs;
+ Vector<int, kMaxBufferLength> advances;
+ int glyphIndex = 0; // The starting glyph of the current chunk.
+
+ // 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.
+ while (glyphIndex < numGlyphs) {
+ // How many chars will be in this chunk?
+ int curLen = min(kMaxBufferLength, numGlyphs - glyphIndex);
+ glyphs.resize(curLen);
+ advances.resize(curLen);
+
+ float currentWidth = 0;
+ for (int i = 0; i < curLen; ++i, ++glyphIndex) {
+ glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
+ horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
+ advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
+ lastHorizontalOffsetRounded += advances[i];
+ currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
+
+ // Bug 26088 - very large positive or negative runs can fail to
+ // render so we clamp the size here. In the specs, negative
+ // letter-spacing is implementation-defined, so this should be
+ // fine, and it matches Safari's implementation. The call actually
+ // seems to crash if kMaxNegativeRun is set to somewhere around
+ // -32830, so we give ourselves a little breathing room.
+ const int maxNegativeRun = -32768;
+ const int maxPositiveRun = 32768;
+ if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun))
+ advances[i] = 0;
+ }
+
+ // Actually draw the glyphs (with retry on failure).
+ bool success = false;
+ for (int executions = 0; executions < 2; ++executions) {
+ success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth);
+ if (!success && !executions) {
+ // Ask the browser to load the font for us and retry.
+ PlatformSupport::ensureFontLoaded(font->platformData().hfont());
+ continue;
+ }
+ break;
+ }
+
+ if (!success)
+ LOG_ERROR("Unable to draw the glyphs after second attempt");
+ }
+}
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) const
+{
+ SkColor color = graphicsContext->platformContext()->effectiveFillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
+ return;
+ if (!alpha || windowsCanHandleDrawTextShadow(graphicsContext) || !windowsCanHandleTextDrawingWithoutShadow(graphicsContext)) {
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ return;
+ }
+ // Draw in two passes: skia for the shadow, GDI for foreground text
+ // pass1: shadow (will use skia)
+ graphicsContext->save();
+ graphicsContext->setFillColor(Color::transparent, graphicsContext->fillColorSpace());
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ graphicsContext->restore();
+ // pass2: foreground text (will use GDI)
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+ graphicsContext->setShadow(shadowOffset, shadowBlur, Color::transparent, shadowColorSpace);
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+}
+#endif
+
FloatRect Font::selectionRectForComplexText(const TextRun& run,
const FloatPoint& point,
int h,
@@ -148,9 +574,40 @@
if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
return;
+#if ENABLE(SKIA_TEXT)
+ HDC hdc = 0;
+#else
+ TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
+
+ HDC hdc = painter.hdc();
+ if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
+ return;
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ if (hdc) {
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+ }
+
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(hdc);
+ SetTextColor(hdc, textColor);
+ state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(),
+ static_cast<int>(point.y() - fontMetrics().ascent()) + shadowOffset.height(), from, to);
+ SetTextColor(hdc, savedTextColor);
+ }
+#endif
// Uniscribe counts the coordinates from the upper left, while WebKit uses
// the baseline, so we have to subtract off the ascent.
- HDC hdc = 0;
state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to);
}
Modified: trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp 2011-10-11 13:11:33 UTC (rev 97149)
@@ -318,6 +318,9 @@
HGDIOBJ oldFont = 0;
int curX = x;
bool firstRun = true;
+#if !ENABLE(SKIA_TEXT)
+ bool useWindowsDrawing = windowsCanHandleTextDrawing(graphicsContext);
+#endif
for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
int itemIndex = m_screenOrder[screenIndex];
@@ -396,14 +399,26 @@
// Pass 0 in when there is no justification.
const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
+#if ENABLE(SKIA_TEXT)
const int* advances = shaping.m_justify.size() ?
&shaping.m_justify[fromGlyph]
: &shaping.m_advance[fromGlyph];
+#else
+ if (useWindowsDrawing) {
+ if (firstRun) {
+ oldFont = SelectObject(dc, shaping.m_hfont);
+ firstRun = false;
+ } else
+ SelectObject(dc, shaping.m_hfont);
+ }
+
+#endif
// Fonts with different ascents can be used to render different
// runs. 'Across-runs' y-coordinate correction needs to be
// adjusted for each font.
bool textOutOk = false;
for (int executions = 0; executions < 2; ++executions) {
+#if ENABLE(SKIA_TEXT)
SkPoint origin;
origin.fX = curX + + innerOffset;
origin.fY = y + m_ascent;
@@ -415,6 +430,32 @@
&shaping.m_offsets[fromGlyph],
&origin);
textOutOk = true;
+#else
+ if (useWindowsDrawing) {
+ HRESULT hr = ScriptTextOut(dc, shaping.m_scriptCache,
+ curX + innerOffset,
+ y - shaping.m_ascentOffset,
+ 0, 0, &item.a, 0, 0,
+ &shaping.m_glyphs[fromGlyph],
+ glyphCount,
+ &shaping.m_advance[fromGlyph],
+ justify,
+ &shaping.m_offsets[fromGlyph]);
+ textOutOk = (hr == S_OK);
+ } else {
+ SkPoint origin;
+ origin.fX = curX + + innerOffset;
+ origin.fY = y + m_ascent;
+ paintSkiaText(graphicsContext,
+ shaping.m_hfont,
+ glyphCount,
+ &shaping.m_glyphs[fromGlyph],
+ &shaping.m_advance[fromGlyph],
+ &shaping.m_offsets[fromGlyph],
+ &origin);
+ textOutOk = true;
+ }
+#endif
if (!textOutOk && 0 == executions) {
// If TextOut is called from the renderer it might fail
Modified: trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp 2011-10-11 13:11:33 UTC (rev 97149)
@@ -579,6 +579,17 @@
return &m_canvas->getDevice()->accessBitmap(false);
}
+bool PlatformContextSkia::isNativeFontRenderingAllowed()
+{
+#if ENABLE(SKIA_TEXT)
+ return false;
+#else
+ if (isAccelerated())
+ return false;
+ return skia::SupportsPlatformPaint(m_canvas);
+#endif
+}
+
void PlatformContextSkia::getImageResamplingHint(IntSize* srcSize, FloatSize* dstSize) const
{
*srcSize = m_imageResamplingHintSrcSize;
Modified: trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h 2011-10-11 13:11:33 UTC (rev 97149)
@@ -167,6 +167,12 @@
bool printing() const { return m_printing; }
void setPrinting(bool p) { m_printing = p; }
+ // Returns if the context allows rendering of fonts using native platform
+ // APIs. If false is returned font rendering is performed using the skia
+ // text drawing APIs.
+ // if SKIA_TEXT is enabled, this always returns false
+ bool isNativeFontRenderingAllowed();
+
void getImageResamplingHint(IntSize* srcSize, FloatSize* dstSize) const;
void setImageResamplingHint(const IntSize& srcSize, const FloatSize& dstSize);
void clearImageResamplingHint();
Modified: trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp 2011-10-11 13:11:33 UTC (rev 97149)
@@ -43,6 +43,60 @@
namespace WebCore {
+#if !ENABLE(SKIA_TEXT)
+bool windowsCanHandleDrawTextShadow(GraphicsContext* context)
+{
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+
+ bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+ return !hasShadow || (!shadowBlur && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
+}
+
+bool windowsCanHandleTextDrawing(GraphicsContext* context)
+{
+ if (!windowsCanHandleTextDrawingWithoutShadow(context))
+ return false;
+
+ // Check for shadow effects.
+ if (!windowsCanHandleDrawTextShadow(context))
+ return false;
+
+ return true;
+}
+
+bool windowsCanHandleTextDrawingWithoutShadow(GraphicsContext* context)
+{
+ // Check for non-translation transforms. Sometimes zooms will look better in
+ // Skia, and sometimes better in Windows. The main problem is that zooming
+ // in using Skia will show you the hinted outlines for the smaller size,
+ // which look weird. All else being equal, it's better to use Windows' text
+ // drawing, so we don't check for zooms.
+ const AffineTransform& matrix = context->getCTM();
+ if (matrix.b() || matrix.c()) // Check for skew.
+ return false;
+
+ // Check for stroke effects.
+ if (context->platformContext()->getTextDrawingMode() != TextModeFill)
+ return false;
+
+ // Check for gradients.
+ if (context->fillGradient() || context->strokeGradient())
+ return false;
+
+ // Check for patterns.
+ if (context->fillPattern() || context->strokePattern())
+ return false;
+
+ if (!context->platformContext()->isNativeFontRenderingAllowed())
+ return false;
+
+ return true;
+}
+#endif
+
static void skiaDrawText(SkCanvas* canvas,
const SkPoint& point,
SkPaint* paint,
Modified: trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.h (97148 => 97149)
--- trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.h 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebCore/platform/graphics/skia/SkiaFontWin.h 2011-10-11 13:11:33 UTC (rev 97149)
@@ -34,12 +34,41 @@
#include <windows.h>
#include <usp10.h>
-class SkPoint;
+struct SkPoint;
namespace WebCore {
class GraphicsContext;
+class PlatformContextSkia;
+#if !ENABLE(SKIA_TEXT)
+// The functions below are used for more complex font drawing (effects such as
+// stroking and more complex transforms) than Windows supports directly. Since
+// Windows drawing is faster you should use windowsCanHandleTextDrawing first to
+// check if using Skia is required at all.
+// Note that the text will look different (no ClearType) so this should only be
+// used when necessary.
+//
+// When you call a Skia* text drawing function, various glyph outlines will be
+// cached. As a result, you should call SkiaWinOutlineCache::removePathsForFont
+// when the font is destroyed so that the cache does not outlive the font (since
+// the HFONTs are recycled).
+//
+// Remember that Skia's text drawing origin is the baseline, like WebKit, not
+// the top, like Windows.
+
+// Returns true if the fillColor and shadowColor are opaque and the text-shadow
+// is not blurred.
+bool windowsCanHandleDrawTextShadow(GraphicsContext*);
+
+// Returns true if advanced font rendering is recommended.
+bool windowsCanHandleTextDrawing(GraphicsContext*);
+
+// Returns true if advanced font rendering is recommended if shadows are
+// disregarded.
+bool windowsCanHandleTextDrawingWithoutShadow(GraphicsContext*);
+#endif
+
// Note that the offsets parameter is optional. If not NULL it represents a
// per glyph offset (such as returned by ScriptPlace Windows API function).
void paintSkiaText(GraphicsContext*,
Modified: trunk/Source/WebKit/chromium/ChangeLog (97148 => 97149)
--- trunk/Source/WebKit/chromium/ChangeLog 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebKit/chromium/ChangeLog 2011-10-11 13:11:33 UTC (rev 97149)
@@ -1,3 +1,12 @@
+2011-10-11 Mike Reed <r...@google.com>
+
+ re-add support for GDI text behind a compile flag
+ https://bugs.webkit.org/show_bug.cgi?id=69530
+
+ Reviewed by James Robinson.
+
+ * features.gypi:
+
2011-10-11 Pavel Podivilov <podivi...@chromium.org>
Unreviewed, roll chromium revision to pick HTML speech input images update.
Modified: trunk/Source/WebKit/chromium/features.gypi (97148 => 97149)
--- trunk/Source/WebKit/chromium/features.gypi 2011-10-11 12:54:19 UTC (rev 97148)
+++ trunk/Source/WebKit/chromium/features.gypi 2011-10-11 13:11:33 UTC (rev 97149)
@@ -79,6 +79,7 @@
'ENABLE_SANDBOX=1',
'ENABLE_SHARED_WORKERS=1',
'ENABLE_SKIA_GPU=<(use_skia_gpu)',
+ 'ENABLE_SKIA_TEXT=<(enable_skia_text)',
'ENABLE_SMOOTH_SCROLLING=1',
'ENABLE_SQL_DATABASE=1',
'ENABLE_SVG=<(enable_svg)',
@@ -109,6 +110,7 @@
'variables': {
'use_accelerated_compositing%': 1,
'use_threaded_compositing%': 0,
+ 'enable_skia_text%': 0,
'enable_svg%': 1,
'enable_touch_events%': 1,
'use_skia_gpu%': 0,
@@ -118,6 +120,7 @@
},
'use_accelerated_compositing%': '<(use_accelerated_compositing)',
'use_threaded_compositing%': '<(use_threaded_compositing)',
+ 'enable_skia_text%': '<(enable_skia_text)',
'enable_svg%': '<(enable_svg)',
'enable_touch_events%': '<(enable_touch_events)',
'use_skia%': '<(use_skia)',
_______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes