summaryrefslogtreecommitdiffstats
path: root/skia
diff options
context:
space:
mode:
authorreed@google.com <reed@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 14:53:37 +0000
committerreed@google.com <reed@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 14:53:37 +0000
commit86cd4854c06e31d6c581d5d439ab97241d7d2fc5 (patch)
treeb83ea1c703e02a50a76d9ea7f92e67328c83009e /skia
parentb1e544f36255f965ba719ee40dde4c9880fd81ce (diff)
downloadchromium_src-86cd4854c06e31d6c581d5d439ab97241d7d2fc5.zip
chromium_src-86cd4854c06e31d6c581d5d439ab97241d7d2fc5.tar.gz
chromium_src-86cd4854c06e31d6c581d5d439ab97241d7d2fc5.tar.bz2
support text drawing instead of asserting
add bool return for LoadPathToDC() since it can fail and the caller needs to know. Review URL: http://codereview.chromium.org/7443006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93395 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia')
-rw-r--r--skia/ext/platform_device_win.cc9
-rw-r--r--skia/ext/platform_device_win.h4
-rw-r--r--skia/ext/vector_platform_device_emf_win.cc188
3 files changed, 168 insertions, 33 deletions
diff --git a/skia/ext/platform_device_win.cc b/skia/ext/platform_device_win.cc
index 17e04b2..ea72165 100644
--- a/skia/ext/platform_device_win.cc
+++ b/skia/ext/platform_device_win.cc
@@ -62,7 +62,7 @@ void PlatformDevice::EndPlatformPaint() {
}
// static
-void PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
+bool PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
switch (path.getFillType()) {
case SkPath::kWinding_FillType: {
int res = SetPolyFillMode(context, WINDING);
@@ -80,11 +80,13 @@ void PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
}
}
BOOL res = BeginPath(context);
- SkASSERT(res != 0);
+ if (!res) {
+ return false;
+ }
CubicPaths paths;
if (!SkPathToCubicPaths(&paths, path))
- return;
+ return false;
std::vector<POINT> points;
for (CubicPaths::const_iterator path(paths.begin()); path != paths.end();
@@ -119,6 +121,7 @@ void PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
res = EndPath(context);
SkASSERT(res != 0);
}
+ return true;
}
// static
diff --git a/skia/ext/platform_device_win.h b/skia/ext/platform_device_win.h
index a5445aa..57afa89 100644
--- a/skia/ext/platform_device_win.h
+++ b/skia/ext/platform_device_win.h
@@ -53,8 +53,8 @@ class SK_API PlatformDevice : public SkDevice {
virtual bool IsNativeFontRenderingAllowed() { return true; }
// Loads a SkPath into the GDI context. The path can there after be used for
- // clipping or as a stroke.
- static void LoadPathToDC(HDC context, const SkPath& path);
+ // clipping or as a stroke. Returns false if the path failed to be loaded.
+ static bool LoadPathToDC(HDC context, const SkPath& path);
// Loads a SkRegion into the GDI context.
static void LoadClippingRegionToDC(HDC context, const SkRegion& region,
diff --git a/skia/ext/vector_platform_device_emf_win.cc b/skia/ext/vector_platform_device_emf_win.cc
index 0789197..eac7977 100644
--- a/skia/ext/vector_platform_device_emf_win.cc
+++ b/skia/ext/vector_platform_device_emf_win.cc
@@ -8,7 +8,9 @@
#include "skia/ext/bitmap_platform_device.h"
#include "skia/ext/skia_utils_win.h"
+#include "third_party/skia/include/core/SkTemplates.h"
#include "third_party/skia/include/core/SkUtils.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
namespace skia {
@@ -227,26 +229,27 @@ void VectorPlatformDeviceEmf::drawPath(const SkDraw& draw,
return;
}
HDC dc = BeginPlatformPaint();
- PlatformDevice::LoadPathToDC(dc, path);
- switch (paint.getStyle()) {
- case SkPaint::kFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- SkASSERT(res != 0);
- break;
- }
- case SkPaint::kStroke_Style: {
- BOOL res = StrokePath(dc);
- SkASSERT(res != 0);
- break;
- }
- case SkPaint::kStrokeAndFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- SkASSERT(res != 0);
- break;
+ if (PlatformDevice::LoadPathToDC(dc, path)) {
+ switch (paint.getStyle()) {
+ case SkPaint::kFill_Style: {
+ BOOL res = StrokeAndFillPath(dc);
+ SkASSERT(res != 0);
+ break;
+ }
+ case SkPaint::kStroke_Style: {
+ BOOL res = StrokePath(dc);
+ SkASSERT(res != 0);
+ break;
+ }
+ case SkPaint::kStrokeAndFill_Style: {
+ BOOL res = StrokeAndFillPath(dc);
+ SkASSERT(res != 0);
+ break;
+ }
+ default:
+ SkASSERT(false);
+ break;
}
- default:
- SkASSERT(false);
- break;
}
EndPlatformPaint();
Cleanup();
@@ -283,14 +286,108 @@ void VectorPlatformDeviceEmf::drawSprite(const SkDraw& draw,
LoadTransformToDC(hdc_, transform_);
}
+/////////////////////////////////////////////////////////////////////////
+
+static bool gdiCanHandleText(const SkPaint& paint) {
+ return !paint.getShader() &&
+ !paint.getPathEffect() &&
+ (SkPaint::kFill_Style == paint.getStyle()) &&
+ (255 == paint.getAlpha());
+}
+
+class SkGDIFontSetup {
+public:
+ SkGDIFontSetup() : fUseGDI(false) {
+ SkDEBUGCODE(fUseGDIHasBeenCalled = false;)
+ }
+ ~SkGDIFontSetup();
+
+ // can only be called once
+ bool useGDI(HDC hdc, const SkPaint&);
+
+private:
+ HDC fHDC;
+ HFONT fNewFont;
+ HFONT fSavedFont;
+ COLORREF fSavedTextColor;
+ bool fUseGDI;
+ SkDEBUGCODE(bool fUseGDIHasBeenCalled;)
+};
+
+bool SkGDIFontSetup::useGDI(HDC hdc, const SkPaint& paint) {
+ SkASSERT(!fUseGDIHasBeenCalled);
+ SkDEBUGCODE(fUseGDIHasBeenCalled = true;)
+
+ fUseGDI = gdiCanHandleText(paint);
+ if (fUseGDI) {
+ fSavedTextColor = GetTextColor(hdc);
+ SetTextColor(hdc, skia::SkColorToCOLORREF(paint.getColor()));
+
+ LOGFONT lf;
+ SkLOGFONTFromTypeface(paint.getTypeface(), &lf);
+ lf.lfHeight = -SkScalarRound(paint.getTextSize());
+ fNewFont = CreateFontIndirect(&lf);
+ fSavedFont = (HFONT)::SelectObject(hdc, fNewFont);
+ }
+ return fUseGDI;
+}
+
+SkGDIFontSetup::~SkGDIFontSetup() {
+ if (fUseGDI) {
+ ::SelectObject(fHDC, fSavedFont);
+ ::DeleteObject(fNewFont);
+ SetTextColor(fHDC, fSavedTextColor);
+ }
+}
+
+static SkScalar getAscent(const SkPaint& paint) {
+ SkPaint::FontMetrics fm;
+ paint.getFontMetrics(&fm);
+ return fm.fAscent;
+}
+
+// return the options int for ExtTextOut. Only valid if the paint's text encoding
+// is not UTF8 (in which case ExtTextOut can't be used).
+static UINT getTextOutOptions(const SkPaint& paint) {
+ if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
+ return ETO_GLYPH_INDEX;
+ } else {
+ SkASSERT(SkPaint::kUTF16_TextEncoding == paint.getTextEncoding());
+ return 0;
+ }
+}
+
void VectorPlatformDeviceEmf::drawText(const SkDraw& draw,
const void* text,
size_t byteLength,
SkScalar x,
SkScalar y,
const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- SkASSERT(false);
+ SkGDIFontSetup setup;
+ if (SkPaint::kUTF8_TextEncoding != paint.getTextEncoding()
+ && setup.useGDI(hdc_, paint)) {
+ UINT options = getTextOutOptions(paint);
+ UINT count = byteLength >> 1;
+ ExtTextOut(hdc_, SkScalarRound(x), SkScalarRound(y + getAscent(paint)),
+ options, 0, reinterpret_cast<const wchar_t*>(text), count, NULL);
+ } else {
+ SkPath path;
+ paint.getTextPath(text, byteLength, x, y, &path);
+ drawPath(draw, path, paint);
+ }
+}
+
+static size_t size_utf8(const char* text) {
+ return SkUTF8_CountUTF8Bytes(text);
+}
+
+static size_t size_utf16(const char* text) {
+ uint16_t c = *reinterpret_cast<const uint16_t*>(text);
+ return SkUTF16_IsHighSurrogate(c) ? 4 : 2;
+}
+
+static size_t size_glyphid(const char* text) {
+ return 2;
}
void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw,
@@ -300,8 +397,46 @@ void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw,
SkScalar constY,
int scalarsPerPos,
const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- SkASSERT(false);
+ SkGDIFontSetup setup;
+ if (2 == scalarsPerPos
+ && SkPaint::kUTF8_TextEncoding != paint.getTextEncoding()
+ && setup.useGDI(hdc_, paint)) {
+ int startX = SkScalarRound(pos[0]);
+ int startY = SkScalarRound(pos[1] + getAscent(paint));
+ const int count = len >> 1;
+ SkAutoSTMalloc<64, INT> storage(count);
+ INT* advances = storage.get();
+ for (int i = 0; i < count - 1; ++i) {
+ advances[i] = SkScalarRound(pos[2] - pos[0]);
+ pos += 2;
+ }
+ ExtTextOut(hdc_, startX, startY, getTextOutOptions(paint), 0,
+ reinterpret_cast<const wchar_t*>(text), count, advances);
+ } else {
+ size_t (*bytesPerCodePoint)(const char*);
+ switch (paint.getTextEncoding()) {
+ case SkPaint::kUTF8_TextEncoding:
+ bytesPerCodePoint = size_utf8;
+ break;
+ case SkPaint::kUTF16_TextEncoding:
+ bytesPerCodePoint = size_utf16;
+ break;
+ default:
+ SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
+ bytesPerCodePoint = size_glyphid;
+ break;
+ }
+
+ const char* curr = reinterpret_cast<const char*>(text);
+ const char* stop = curr + len;
+ while (curr < stop) {
+ SkScalar y = (1 == scalarsPerPos) ? constY : pos[1];
+ size_t bytes = bytesPerCodePoint(curr);
+ drawText(draw, curr, bytes, pos[0], y, paint);
+ curr += bytes;
+ pos += scalarsPerPos;
+ }
+ }
}
void VectorPlatformDeviceEmf::drawTextOnPath(const SkDraw& draw,
@@ -409,11 +544,9 @@ bool VectorPlatformDeviceEmf::ApplyPaint(const SkPaint& paint) {
// The path effect should be processed before arriving here.
SkASSERT(!paint.getPathEffect());
- // These aren't used in the code. Verify this assumption.
- SkASSERT(!paint.getColorFilter());
+ // This isn't used in the code. Verify this assumption.
SkASSERT(!paint.getRasterizer());
// Reuse code to load Win32 Fonts.
- SkASSERT(!paint.getTypeface());
return true;
}
@@ -717,7 +850,7 @@ void VectorPlatformDeviceEmf::InternalDrawBitmap(const SkBitmap& bitmap,
DeleteObject(hbitmap);
DeleteDC(bitmap_dc);
} else {
- BOOL result = StretchDIBits(dc,
+ int nCopied = StretchDIBits(dc,
x, y, // Destination origin.
src_size_x, src_size_y,
0, 0, // Source origin.
@@ -726,7 +859,6 @@ void VectorPlatformDeviceEmf::InternalDrawBitmap(const SkBitmap& bitmap,
reinterpret_cast<const BITMAPINFO*>(&hdr),
DIB_RGB_COLORS,
SRCCOPY);
- SkASSERT(result);
}
EndPlatformPaint();
Cleanup();