summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/chromium/FontChromiumWin.cpp')
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp541
1 files changed, 0 insertions, 541 deletions
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
deleted file mode 100644
index 1a00833..0000000
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Inc.
- * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "Font.h"
-
-#include "ChromiumBridge.h"
-#include "FontFallbackList.h"
-#include "GlyphBuffer.h"
-#include "NotImplemented.h"
-#include "PlatformContextSkia.h"
-#include "SimpleFontData.h"
-#include "SkiaFontWin.h"
-#include "SkiaUtils.h"
-#include "TransparencyWin.h"
-#include "UniscribeHelperTextRun.h"
-
-#include "skia/ext/platform_canvas_win.h"
-#include "skia/ext/skia_utils_win.h" // FIXME: remove this dependency.
-
-#include <windows.h>
-
-namespace WebCore {
-
-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 = m_transparency.platformContext()->canvas()->beginPlatformPaint();
- 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();
- m_platformContext->canvas()->endPlatformPaint();
-}
-
-// 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, int 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));
-
- return IntRect(m_point.x() - (m_font->ascent() + m_font->descent()) / 2,
- m_point.y() - m_font->ascent() - m_font->lineGap(),
- totalWidth + m_font->ascent() + m_font->descent(),
- m_font->lineSpacing());
-}
-
-bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
- const WORD* glyphs,
- const int* advances,
- int startAdvance) const
-{
- if (!m_useGDI) {
- SkPoint origin = m_point;
- origin.fX += startAdvance;
- return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
- numGlyphs, glyphs, advances, 0, &origin);
- }
-
- 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->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 {
- 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.
- return IntRect(left - (m_font->ascent() + m_font->descent()) / 2,
- m_point.y() - m_font->ascent() - m_font->lineGap(),
- (right - left) + m_font->ascent() + m_font->descent(),
- m_font->lineSpacing());
-}
-
-} // namespace
-
-bool Font::canReturnFallbackFontsForComplexText()
-{
- return false;
-}
-
-void Font::drawGlyphs(GraphicsContext* graphicsContext,
- const SimpleFontData* font,
- const GlyphBuffer& glyphBuffer,
- int from,
- int numGlyphs,
- const FloatPoint& point) const
-{
- graphicsContext->platformContext()->prepareForSoftwareDraw();
-
- 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)
- return;
-
- 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.
- int curAdvance = 0; // How far from the left the current chunk is.
- while (glyphIndex < numGlyphs) {
- // How many chars will be in this chunk?
- int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
- glyphs.resize(curLen);
- advances.resize(curLen);
-
- int curWidth = 0;
- for (int i = 0; i < curLen; ++i, ++glyphIndex) {
- glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
- advances[i] = static_cast<int>(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 ((curWidth + advances[i] < maxNegativeRun) || (curWidth + advances[i] > maxPositiveRun))
- advances[i] = 0;
- curWidth += advances[i];
- }
-
- // 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], curAdvance);
- if (!success && executions == 0) {
- // Ask the browser to load the font for us and retry.
- ChromiumBridge::ensureFontLoaded(font->platformData().hfont());
- continue;
- }
- break;
- }
-
- if (!success)
- LOG_ERROR("Unable to draw the glyphs after second attempt");
-
- curAdvance += curWidth;
- }
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run,
- const FloatPoint& point,
- int h,
- int from,
- int to) const
-{
- UniscribeHelperTextRun state(run, *this);
- float left = static_cast<float>(point.x() + state.characterToX(from));
- float right = static_cast<float>(point.x() + state.characterToX(to));
-
- // If the text is RTL, left will actually be after right.
- if (left < right)
- return FloatRect(left, point.y(),
- right - left, static_cast<float>(h));
-
- return FloatRect(right, point.y(),
- left - right, static_cast<float>(h));
-}
-
-void Font::drawComplexText(GraphicsContext* graphicsContext,
- const TextRun& run,
- const FloatPoint& point,
- int from,
- int to) const
-{
- PlatformGraphicsContext* context = graphicsContext->platformContext();
- UniscribeHelperTextRun state(run, *this);
-
- 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)
- 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() - 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.
- state.draw(graphicsContext, hdc, static_cast<int>(point.x()),
- static_cast<int>(point.y() - ascent()), from, to);
-
- context->canvas()->endPlatformPaint();
-}
-
-void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
-{
- notImplemented();
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
-{
- UniscribeHelperTextRun state(run, *this);
- return static_cast<float>(state.width());
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
- bool includePartialGlyphs) const
-{
- // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
- // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
- int x = static_cast<int>(xFloat);
-
- // Mac code ignores includePartialGlyphs, and they don't know what it's
- // supposed to do, so we just ignore it as well.
- UniscribeHelperTextRun state(run, *this);
- int charIndex = state.xToCharacter(x);
-
- // XToCharacter will return -1 if the position is before the first
- // character (we get called like this sometimes).
- if (charIndex < 0)
- charIndex = 0;
- return charIndex;
-}
-
-} // namespace WebCore