summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/skia/SkiaFontWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/skia/SkiaFontWin.cpp')
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.cpp358
1 files changed, 0 insertions, 358 deletions
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
deleted file mode 100644
index 5046c50..0000000
--- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (c) 2008, 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 "SkiaFontWin.h"
-
-#include "AffineTransform.h"
-#include "PlatformContextSkia.h"
-#include "Gradient.h"
-#include "Pattern.h"
-#include "SkCanvas.h"
-#include "SkPaint.h"
-#include "SkShader.h"
-
-#include <wtf/ListHashSet.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-struct CachedOutlineKey {
- CachedOutlineKey() : font(0), glyph(0), path(0) {}
- CachedOutlineKey(HFONT f, WORD g) : font(f), glyph(g), path(0) {}
-
- HFONT font;
- WORD glyph;
-
- // The lifetime of this pointer is managed externally to this class. Be sure
- // to call DeleteOutline to remove items.
- SkPath* path;
-};
-
-const bool operator==(const CachedOutlineKey& a, const CachedOutlineKey& b)
-{
- return a.font == b.font && a.glyph == b.glyph;
-}
-
-struct CachedOutlineKeyHash {
- static unsigned hash(const CachedOutlineKey& key)
- {
- unsigned keyBytes;
- memcpy(&keyBytes, &key.font, sizeof(unsigned));
- return keyBytes + key.glyph;
- }
-
- static unsigned equal(const CachedOutlineKey& a, const CachedOutlineKey& b)
- {
- return a.font == b.font && a.glyph == b.glyph;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-// The global number of glyph outlines we'll cache.
-static const int outlineCacheSize = 256;
-
-typedef ListHashSet<CachedOutlineKey, outlineCacheSize+1, CachedOutlineKeyHash> OutlineCache;
-
-// FIXME: Convert from static constructor to accessor function. WebCore tries to
-// avoid global constructors to save on start-up time.
-static OutlineCache outlineCache;
-
-static SkScalar FIXEDToSkScalar(FIXED fixed)
-{
- SkFixed skFixed;
- memcpy(&skFixed, &fixed, sizeof(SkFixed));
- return SkFixedToScalar(skFixed);
-}
-
-// Removes the given key from the cached outlines, also deleting the path.
-static void deleteOutline(OutlineCache::iterator deleteMe)
-{
- delete deleteMe->path;
- outlineCache.remove(deleteMe);
-}
-
-static void addPolyCurveToPath(const TTPOLYCURVE* polyCurve, SkPath* path)
-{
- switch (polyCurve->wType) {
- case TT_PRIM_LINE:
- for (WORD i = 0; i < polyCurve->cpfx; i++) {
- path->lineTo(FIXEDToSkScalar(polyCurve->apfx[i].x), -FIXEDToSkScalar(polyCurve->apfx[i].y));
- }
- break;
-
- case TT_PRIM_QSPLINE:
- // FIXME: doesn't this duplicate points if we do the loop > once?
- for (WORD i = 0; i < polyCurve->cpfx - 1; i++) {
- SkScalar bx = FIXEDToSkScalar(polyCurve->apfx[i].x);
- SkScalar by = FIXEDToSkScalar(polyCurve->apfx[i].y);
-
- SkScalar cx = FIXEDToSkScalar(polyCurve->apfx[i + 1].x);
- SkScalar cy = FIXEDToSkScalar(polyCurve->apfx[i + 1].y);
- if (i < polyCurve->cpfx - 2) {
- // We're not the last point, compute C.
- cx = SkScalarAve(bx, cx);
- cy = SkScalarAve(by, cy);
- }
-
- // Need to flip the y coordinates since the font's coordinate system is
- // flipped from ours vertically.
- path->quadTo(bx, -by, cx, -cy);
- }
- break;
-
- case TT_PRIM_CSPLINE:
- // FIXME
- break;
- }
-}
-
-// The size of the glyph path buffer.
-static const int glyphPathBufferSize = 4096;
-
-// Fills the given SkPath with the outline for the given glyph index. The font
-// currently selected into the given DC is used. Returns true on success.
-static bool getPathForGlyph(HDC dc, WORD glyph, SkPath* path)
-{
- char buffer[glyphPathBufferSize];
- GLYPHMETRICS gm;
- MAT2 mat = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; // Each one is (fract,value).
-
- DWORD totalSize = GetGlyphOutlineW(dc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE,
- &gm, glyphPathBufferSize, buffer, &mat);
- if (totalSize == GDI_ERROR)
- return false;
-
- const char* curGlyph = buffer;
- const char* endGlyph = &buffer[totalSize];
- while (curGlyph < endGlyph) {
- const TTPOLYGONHEADER* polyHeader =
- reinterpret_cast<const TTPOLYGONHEADER*>(curGlyph);
- path->moveTo(FIXEDToSkScalar(polyHeader->pfxStart.x),
- -FIXEDToSkScalar(polyHeader->pfxStart.y));
-
- const char* curPoly = curGlyph + sizeof(TTPOLYGONHEADER);
- const char* endPoly = curGlyph + polyHeader->cb;
- while (curPoly < endPoly) {
- const TTPOLYCURVE* polyCurve =
- reinterpret_cast<const TTPOLYCURVE*>(curPoly);
- addPolyCurveToPath(polyCurve, path);
- curPoly += sizeof(WORD) * 2 + sizeof(POINTFX) * polyCurve->cpfx;
- }
- path->close();
- curGlyph += polyHeader->cb;
- }
-
- return true;
-}
-
-// Returns a SkPath corresponding to the give glyph in the given font. The font
-// should be selected into the given DC. The returned path is owned by the
-// hashtable. Returns 0 on error.
-const SkPath* SkiaWinOutlineCache::lookupOrCreatePathForGlyph(HDC hdc, HFONT font, WORD glyph)
-{
- CachedOutlineKey key(font, glyph);
- OutlineCache::iterator found = outlineCache.find(key);
- if (found != outlineCache.end()) {
- // Keep in MRU order by removing & reinserting the value.
- key = *found;
- outlineCache.remove(found);
- outlineCache.add(key);
- return key.path;
- }
-
- key.path = new SkPath;
- if (!getPathForGlyph(hdc, glyph, key.path))
- return 0;
-
- if (outlineCache.size() > outlineCacheSize)
- // The cache is too big, find the oldest value (first in the list).
- deleteOutline(outlineCache.begin());
-
- outlineCache.add(key);
- return key.path;
-}
-
-
-void SkiaWinOutlineCache::removePathsForFont(HFONT hfont)
-{
- // ListHashSet isn't the greatest structure for deleting stuff out of, but
- // removing entries will be relatively rare (we don't remove fonts much, nor
- // do we draw out own glyphs using these routines much either).
- //
- // We keep a list of all glyphs we're removing which we do in a separate
- // pass.
- Vector<CachedOutlineKey> outlinesToDelete;
- for (OutlineCache::iterator i = outlineCache.begin();
- i != outlineCache.end(); ++i)
- outlinesToDelete.append(*i);
-
- for (Vector<CachedOutlineKey>::iterator i = outlinesToDelete.begin();
- i != outlinesToDelete.end(); ++i)
- deleteOutline(outlineCache.find(*i));
-}
-
-bool windowsCanHandleDrawTextShadow(GraphicsContext *context)
-{
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- ColorSpace shadowColorSpace;
-
- bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
- return (hasShadow && (shadowBlur == 0) && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
-}
-
-bool windowsCanHandleTextDrawing(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;
-
- // Check for shadow effects.
- if (context->platformContext()->getDrawLooper() && (!windowsCanHandleDrawTextShadow(context)))
- return false;
-
- return true;
-}
-
-// Draws the given text string using skia. Note that gradient or
-// pattern may be NULL, in which case a solid colour is used.
-static bool skiaDrawText(HFONT hfont,
- HDC dc,
- SkCanvas* canvas,
- const SkPoint& point,
- SkPaint* paint,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- int numGlyphs)
-{
- float x = point.fX, y = point.fY;
-
- for (int i = 0; i < numGlyphs; i++) {
- const SkPath* path = SkiaWinOutlineCache::lookupOrCreatePathForGlyph(dc, hfont, glyphs[i]);
- if (!path)
- return false;
-
- float offsetX = 0.0f, offsetY = 0.0f;
- if (offsets && (offsets[i].du != 0 || offsets[i].dv != 0)) {
- offsetX = offsets[i].du;
- offsetY = offsets[i].dv;
- }
-
- SkPath newPath;
- newPath.addPath(*path, x + offsetX, y + offsetY);
- canvas->drawPath(newPath, *paint);
-
- x += advances[i];
- }
-
- return true;
-}
-
-bool paintSkiaText(GraphicsContext* context,
- HFONT hfont,
- int numGlyphs,
- const WORD* glyphs,
- const int* advances,
- const GOFFSET* offsets,
- const SkPoint* origin)
-{
- HDC dc = GetDC(0);
- HGDIOBJ oldFont = SelectObject(dc, hfont);
-
- PlatformContextSkia* platformContext = context->platformContext();
- TextDrawingModeFlags textMode = platformContext->getTextDrawingMode();
-
- // Filling (if necessary). This is the common case.
- SkPaint paint;
- platformContext->setupPaintForFilling(&paint);
- paint.setFlags(SkPaint::kAntiAlias_Flag);
- bool didFill = false;
-
- if ((textMode & TextModeFill) && SkColorGetA(paint.getColor())) {
- if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
- &glyphs[0], &advances[0], &offsets[0], numGlyphs))
- return false;
- didFill = true;
- }
-
- // Stroking on top (if necessary).
- if ((textMode & TextModeStroke)
- && platformContext->getStrokeStyle() != NoStroke
- && platformContext->getStrokeThickness() > 0) {
-
- paint.reset();
- platformContext->setupPaintForStroking(&paint, 0, 0);
- paint.setFlags(SkPaint::kAntiAlias_Flag);
- if (didFill) {
- // If there is a shadow and we filled above, there will already be
- // a shadow. We don't want to draw it again or it will be too dark
- // and it will go on top of the fill.
- //
- // Note that this isn't strictly correct, since the stroke could be
- // very thick and the shadow wouldn't account for this. The "right"
- // thing would be to draw to a new layer and then draw that layer
- // with a shadow. But this is a lot of extra work for something
- // that isn't normally an issue.
- SkSafeUnref(paint.setLooper(0));
- }
-
- if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
- &glyphs[0], &advances[0], &offsets[0], numGlyphs))
- return false;
- }
-
- SelectObject(dc, oldFont);
- ReleaseDC(0, dc);
-
- return true;
-}
-
-} // namespace WebCore