Unreviewed, rolling out r93870.

http://trac.webkit.org/changeset/93870
https://bugs.webkit.org/show_bug.cgi?id=65203

Broke i18n chromium tests

Source/WebCore:

* 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::drawGlyphs):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::hdc):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter):
(WebCore::drawGlyphsWin):
(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:

LayoutTests:

* platform/chromium/test_expectations.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@93881 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 79465142
2011-08-26 Pavel Podivilov <podivilov@chromium.org>
Unreviewed, rolling out r93870.
http://trac.webkit.org/changeset/93870
https://bugs.webkit.org/show_bug.cgi?id=65203
Broke i18n chromium tests
* platform/chromium/test_expectations.txt:
2011-08-26 Martin Robinson <mrobinson@igalia.com>
Removing some tests from the GTK+ skipped lists that have results now
......@@ -1780,84 +1780,6 @@ BUGCR42875 SKIP WONTFIX : sputnik = TEXT
BUGWK38705 : http/tests/security/sandbox-inherit-to-initial-document-2.html = TEXT
// Switching windows over from GDI to Skia for all text rendering.
// When that lands, we will rebaseline these images.
BUGWK65203 WIN : fast/borders/border-antialiasing.html = IMAGE
BUGWK65203 WIN : fast/reflections/reflection-overflow-hidden.html = IMAGE
BUGWK65203 WIN : fast/repaint/reflection-redraw.html = IMAGE
BUGWK65203 WIN : fast/text/atsui-spacing-features.html = IMAGE
BUGWK65203 WIN : fast/text/cg-vs-atsui.html = IMAGE
BUGWK65203 WIN : fast/text/complex-text-opacity.html = IMAGE
BUGWK65203 WIN : fast/text/international/complex-character-based-fallback.html = IMAGE
BUGWK65203 WIN : fast/text/international/danda-space.html = IMAGE
BUGWK65203 WIN : fast/text/international/thai-baht-space.html = IMAGE
BUGWK65203 WIN : fast/text/international/thai-line-breaks.html = IMAGE
BUGWK65203 WIN : media/audio-repaint.html = IMAGE
BUGWK65203 WIN : platform/win/fast/text/uniscribe-missing-glyph.html = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1-SE/text-intro-05-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-37-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-39-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-40-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-41-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-46-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-60-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-61-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-62-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-63-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-64-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-65-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-66-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-67-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-68-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-69-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-70-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-81-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-82-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/animate-elem-83-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/pservers-grad-07-b.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/struct-frag-02-t.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/text-align-04-b.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/text-align-05-b.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/text-align-06-b.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/text-path-01-b.svg = IMAGE
BUGWK65203 WIN : svg/W3C-SVG-1.1/text-text-05-t.svg = IMAGE
BUGWK65203 WIN : svg/as-background-image/animated-svg-as-background.html = IMAGE
BUGWK65203 WIN : svg/as-image/animated-svg-as-image.html = IMAGE
BUGWK65203 WIN : svg/batik/filters/feTile.svg = IMAGE
BUGWK65203 WIN : svg/batik/filters/filterRegions.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/longTextOnPath.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textAnchor.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textFeatures.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textLayout.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textPCDATA.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textProperties.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textProperties2.svg = IMAGE
BUGWK65203 WIN : svg/batik/text/textStyles.svg = IMAGE
BUGWK65203 WIN : svg/carto.net/textbox.svg = IMAGE
BUGWK65203 WIN : svg/carto.net/window.svg = IMAGE
BUGWK65203 WIN : svg/css/text-shadow-multiple.xhtml = IMAGE
BUGWK65203 WIN : svg/custom/js-late-clipPath-and-object-creation.svg = IMAGE
BUGWK65203 WIN : svg/custom/js-late-clipPath-creation.svg = IMAGE
BUGWK65203 WIN : svg/custom/linking-a-03-b-viewBox.svg = IMAGE
BUGWK65203 WIN : svg/custom/linking-uri-01-b.svg = IMAGE
//BUGWK65203 WIN : svg/custom/svg-fonts-fallback.xhtml = IMAGE
BUGWK65203 WIN : svg/dynamic-updates/SVGTextElement-dom-lengthAdjust-attr.html = IMAGE
BUGWK65203 WIN : svg/dynamic-updates/SVGTextElement-svgdom-lengthAdjust-prop.html = IMAGE
BUGWK65203 WIN : svg/hixie/mixed/009.xml = IMAGE
BUGWK65203 WIN : svg/text/foreignObject-text-clipping-bug.xml = IMAGE
BUGWK65203 WIN : svg/text/scaling-font-with-geometric-precision.html = IMAGE
BUGWK65203 WIN : svg/text/text-align-01-b.svg = IMAGE
BUGWK65203 WIN : svg/text/text-align-05-b.svg = IMAGE
BUGWK65203 WIN : svg/text/text-align-06-b.svg = IMAGE
BUGWK65203 WIN : svg/text/text-intro-05-t.svg = IMAGE
BUGWK65203 WIN : svg/text/text-path-01-b.svg = IMAGE
BUGWK65203 WIN : svg/text/textPathBoundsBug.svg = IMAGE
BUGWK65203 WIN : svg/zoom/page/zoom-coords-viewattr-01-b.svg = IMAGE
BUGWK65203 WIN : svg/zoom/page/zoom-hixie-mixed-008.xml = IMAGE
BUGWK65203 WIN : svg/zoom/page/zoom-hixie-mixed-009.xml = IMAGE
BUGWK65203 WIN : svg/zoom/text/zoom-coords-viewattr-01-b.svg = IMAGE
BUGWK65203 WIN : svg/zoom/text/zoom-hixie-mixed-009.xml = IMAGE
// WebKit roll 58791:58807
BUGCR43319 LINUX DEBUG : fast/forms/select-empty-option-height.html = PASS TIMEOUT
......
2011-08-26 Pavel Podivilov <podivilov@chromium.org>
Unreviewed, rolling out r93870.
http://trac.webkit.org/changeset/93870
https://bugs.webkit.org/show_bug.cgi?id=65203
Broke i18n chromium tests
* 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::drawGlyphs):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::hdc):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter):
(WebCore::TransparencyAwareFontPainter::TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter):
(WebCore::drawGlyphsWin):
(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-08-26 Alexei Svitkine <asvitkine@chromium.org>
Chromium Mac: Use a custom pattern image for rubber banding overhang area
......@@ -62,8 +62,14 @@ bool canvasHasMultipleLayers(const SkCanvas* canvas)
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
......@@ -72,6 +78,20 @@ protected:
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,
......@@ -79,7 +99,88 @@ TransparencyAwareFontPainter::TransparencyAwareFontPainter(GraphicsContext* cont
: 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; // Nothing to do.
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.
......@@ -90,10 +191,13 @@ class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
const GlyphBuffer&,
int from, int numGlyphs,
const FloatPoint&);
~TransparencyAwareGlyphPainter();
// Draws the partial string of glyphs, starting at |startAdvance| to the
// left of m_point.
void drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const;
// 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();
......@@ -102,6 +206,10 @@ class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
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(
......@@ -115,9 +223,21 @@ TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter(
, 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.
......@@ -134,15 +254,47 @@ IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
fontMetrics.lineSpacing());
}
void TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
const WORD* glyphs,
const int* advances,
float startAdvance) const
{
SkPoint origin = m_point;
origin.fX += SkFloatToScalar(startAdvance);
paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
numGlyphs, glyphs, advances, 0, &origin);
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 == 0);
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 {
......@@ -152,6 +304,10 @@ class TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
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();
......@@ -173,6 +329,11 @@ TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter(
, m_run(run)
, m_from(from)
, m_to(to)
{
init();
}
TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter()
{
}
......@@ -264,7 +425,20 @@ static void drawGlyphsWin(GraphicsContext* graphicsContext,
advances[i] = 0;
}
painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth);
// 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 == 0) {
// Ask the browser to load the font for us and retry.
PlatformBridge::ensureFontLoaded(font->platformData().hfont());
continue;
}
break;
}
if (!success)
LOG_ERROR("Unable to draw the glyphs after second attempt");
}
}
......@@ -318,9 +492,37 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
return;
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);
}
// 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);
}
......
......@@ -269,6 +269,7 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
HGDIOBJ oldFont = 0;
int curX = x;
bool firstRun = true;
bool useWindowsDrawing = windowsCanHandleTextDrawing(graphicsContext);
for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
int itemIndex = m_screenOrder[screenIndex];
......@@ -347,22 +348,43 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
// Pass 0 in when there is no justification.
const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
if (useWindowsDrawing) {
if (firstRun) {
oldFont = SelectObject(dc, shaping.m_hfont);
firstRun = false;
} else
SelectObject(dc, shaping.m_hfont);
}
// 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) {
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;
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;
}
if (!textOutOk && 0 == executions) {
// If TextOut is called from the renderer it might fail
......
......@@ -578,6 +578,17 @@ const SkBitmap* PlatformContextSkia::bitmap() const
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;
......
......@@ -168,6 +168,11 @@ public:
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.
bool isNativeFontRenderingAllowed();
void getImageResamplingHint(IntSize* srcSize, FloatSize* dstSize) const;
void setImageResamplingHint(const IntSize& srcSize, const FloatSize& dstSize);
void clearImageResamplingHint();
......
......@@ -43,6 +43,58 @@
namespace WebCore {
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() != 0 || matrix.c() != 0) // 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;
}
static void skiaDrawText(SkCanvas* canvas,
const SkPoint& point,
SkPaint* paint,
......
......@@ -39,6 +39,33 @@ class SkPoint;
namespace WebCore {
class GraphicsContext;
class PlatformContextSkia;
// 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).
//