Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Unified Diff: webkit/port/platform/graphics/skia/SkiaFontWin.cpp

Issue 8615: Add support for transformed, stoked, shadowed, filled text. We do this by... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/port/platform/graphics/skia/SkiaFontWin.cpp
===================================================================
--- webkit/port/platform/graphics/skia/SkiaFontWin.cpp (revision 0)
+++ webkit/port/platform/graphics/skia/SkiaFontWin.cpp (revision 0)
@@ -0,0 +1,265 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+
+#include "WTF/ListHashSet.h"
+#include "WTF/Vector.h"
+
+#include "SkiaFontWin.h"
+
+#include "SkCanvas.h"
+#include "SkPaint.h"
+
+namespace WebCore {
+
+namespace {
+
+struct CachedOutlineKey {
+ CachedOutlineKey() : font(NULL), glyph(0), path(NULL) {}
+ CachedOutlineKey(HFONT f, WORD g) : font(f), glyph(g), path(NULL) {}
+
+ 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)
+ {
+ return bit_cast<unsigned>(key.font) + 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;
+};
+
+typedef ListHashSet<CachedOutlineKey, CachedOutlineKeyHash> OutlineCache;
+OutlineCache outlineCache;
+
+// The global number of glyph outlines we'll cache.
+const int outlineCacheSize = 256;
+
+inline FIXED SkScalarToFIXED(SkScalar x)
+{
+ return bit_cast<FIXED>(SkScalarToFixed(x));
+}
+
+inline SkScalar FIXEDToSkScalar(FIXED fixed)
+{
+ return SkFixedToScalar(bit_cast<SkFixed>(fixed));
+}
+
+// Removes the given key from the cached outlines, also deleting the path.
+void DeleteOutline(OutlineCache::iterator deleteMe)
+{
+ delete deleteMe->path;
+ outlineCache.remove(deleteMe);
+}
+
+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(brettw) 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
M-A Ruel 2008/12/15 19:54:51 80 cols, if you care.
+ // flipped from ours vertically.
+ path->quadTo(bx, -by, cx, -cy);
+ }
+ break;
+
+ case TT_PRIM_CSPLINE:
+ // FIXME
+ break;
+ }
+}
+
+// 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.
+bool GetPathForGlyph(HDC dc, WORD glyph, SkPath* path)
+{
+ char buffer[4096];
+ 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, arraysize(buffer), 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;
+ }
+ curGlyph += polyHeader->cb;
+ }
+
+ path->close();
+ 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 NULL on error.
+const SkPath* GetCachedPathForGlyph(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 NULL;
+
+ 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;
+}
+
+} // namespace
+
+bool SkiaDrawText(HFONT hfont,
+ SkCanvas* canvas,
+ const SkPoint& point,
+ SkPaint* paint,
+ const WORD* glyphs,
+ const int* advances,
+ int num_glyphs)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ old_font = SelectObject(dc, hfont);
+
+ canvas->save();
+ canvas->translate(point.fX, point.fY);
+
+ for (int i = 0; i < num_glyphs; i++) {
+ const SkPath* path = GetCachedPathForGlyph(dc, hfont, glyphs[i]);
+ if (!path)
+ return false;
+ canvas->drawPath(*path, *paint);
+ canvas->translate(advances[i], 0);
+ }
+
+ canvas->restore();
+
+ SelectObject(dc, old_font);
+ ReleaseDC(0, dc);
+ return true;
+}
+
+/* TODO(brettw) finish this implementation
+bool SkiaDrawComplexText(HFONT font,
+ SkCanvas* canvas,
+ const SkPoint& point,
+ SkPaint* paint
+ UINT fuOptions,
+ const SCRIPT_ANALYSIS* psa,
+ const WORD* pwGlyphs,
+ int cGlyphs,
+ const int* advances,
+ const int* justifies,
+ const GOFFSET* glyph_offsets)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ old_font = SelectObject(dc, hfont);
+
+ canvas->save();
+ canvas->translate(point.fX, point.fY);
+
+ for (int i = 0; i < cGlyphs; i++) {
+ canvas->translate(glyph_offsets[i].du, glyph_offsets[i].dv);
+
+
+
+
+ // Undo the offset for this glyph.
+ canvas->translate(-glyph_offsets[i].du, -glyph_offsets[i].dv);
+
+ // And advance to where we're drawing the next one. We use the justifies
+ // run since that is the justified advances for each character, rather than
+ // the adnvaces one.
+ canvas->translate(justifies[i], 0);
+ }
+
+ canvas->restore();
+
+ SelectObject(dc, old_font);
+ ReleaseDC(0, dc);
+}*/
+
+void RemoveFontFromSkiaFontWinCache(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;
M-A Ruel 2008/12/15 19:54:51 I guess Vector<OutlineCache::iterator> would break
+ 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));
+}
+
+} // namespace WebCore
Property changes on: webkit\port\platform\graphics\skia\SkiaFontWin.cpp
___________________________________________________________________
Added: svn:mergeinfo

Powered by Google App Engine
This is Rietveld 408576698