summaryrefslogtreecommitdiffstats
path: root/base/gfx/vector_device.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/gfx/vector_device.cc')
-rw-r--r--base/gfx/vector_device.cc612
1 files changed, 0 insertions, 612 deletions
diff --git a/base/gfx/vector_device.cc b/base/gfx/vector_device.cc
deleted file mode 100644
index 26da338..0000000
--- a/base/gfx/vector_device.cc
+++ /dev/null
@@ -1,612 +0,0 @@
-// 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 "base/gfx/vector_device.h"
-
-#include "base/gfx/gdi_util.h"
-#include "base/gfx/skia_utils.h"
-#include "base/logging.h"
-#include "base/scoped_handle.h"
-
-#include "SkUtils.h"
-
-namespace gfx {
-
-VectorDevice* VectorDevice::create(HDC dc, int width, int height) {
- InitializeDC(dc);
-
- // Link the SkBitmap to the current selected bitmap in the device context.
- SkBitmap bitmap;
- HGDIOBJ selected_bitmap = GetCurrentObject(dc, OBJ_BITMAP);
- bool succeeded = false;
- if (selected_bitmap != NULL) {
- BITMAP bitmap_data;
- if (GetObject(selected_bitmap, sizeof(BITMAP), &bitmap_data) ==
- sizeof(BITMAP)) {
- // The context has a bitmap attached. Attach our SkBitmap to it.
- // Warning: If the bitmap gets unselected from the HDC, VectorDevice has
- // no way to detect this, so the HBITMAP could be released while SkBitmap
- // still has a reference to it. Be cautious.
- if (width == bitmap_data.bmWidth &&
- height == bitmap_data.bmHeight) {
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- bitmap_data.bmWidth,
- bitmap_data.bmHeight,
- bitmap_data.bmWidthBytes);
- bitmap.setPixels(bitmap_data.bmBits);
- succeeded = true;
- }
- }
- }
-
- if (!succeeded)
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
-
- return new VectorDevice(dc, bitmap);
-}
-
-VectorDevice::VectorDevice(HDC dc, const SkBitmap& bitmap)
- : PlatformDeviceWin(bitmap),
- hdc_(dc),
- previous_brush_(NULL),
- previous_pen_(NULL) {
- transform_.reset();
-}
-
-VectorDevice::~VectorDevice() {
- DCHECK(previous_brush_ == NULL);
- DCHECK(previous_pen_ == NULL);
-}
-
-
-void VectorDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
- // TODO(maruel): Bypass the current transformation matrix.
- SkRect rect;
- rect.fLeft = 0;
- rect.fTop = 0;
- rect.fRight = SkIntToScalar(width() + 1);
- rect.fBottom = SkIntToScalar(height() + 1);
- drawRect(draw, rect, paint);
-}
-
-void VectorDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
- size_t count, const SkPoint pts[],
- const SkPaint& paint) {
- if (!count)
- return;
-
- if (mode == SkCanvas::kPoints_PointMode) {
- NOTREACHED();
- return;
- }
-
- SkPaint tmp_paint(paint);
- tmp_paint.setStyle(SkPaint::kStroke_Style);
-
- // Draw a path instead.
- SkPath path;
- switch (mode) {
- case SkCanvas::kLines_PointMode:
- if (count % 2) {
- NOTREACHED();
- return;
- }
- for (size_t i = 0; i < count / 2; ++i) {
- path.moveTo(pts[2 * i]);
- path.lineTo(pts[2 * i + 1]);
- }
- break;
- case SkCanvas::kPolygon_PointMode:
- path.moveTo(pts[0]);
- for (size_t i = 1; i < count; ++i) {
- path.lineTo(pts[i]);
- }
- break;
- default:
- NOTREACHED();
- return;
- }
- // Draw the calculated path.
- drawPath(draw, path, tmp_paint);
-}
-
-void VectorDevice::drawRect(const SkDraw& draw, const SkRect& rect,
- const SkPaint& paint) {
- if (paint.getPathEffect()) {
- // Draw a path instead.
- SkPath path_orginal;
- path_orginal.addRect(rect);
-
- // Apply the path effect to the rect.
- SkPath path_modified;
- paint.getFillPath(path_orginal, &path_modified);
-
- // Removes the path effect from the temporary SkPaint object.
- SkPaint paint_no_effet(paint);
- paint_no_effet.setPathEffect(NULL)->safeUnref();
-
- // Draw the calculated path.
- drawPath(draw, path_modified, paint_no_effet);
- return;
- }
-
- if (!ApplyPaint(paint)) {
- return;
- }
- HDC dc = getBitmapDC();
- if (!Rectangle(dc, SkScalarRound(rect.fLeft),
- SkScalarRound(rect.fTop),
- SkScalarRound(rect.fRight),
- SkScalarRound(rect.fBottom))) {
- NOTREACHED();
- }
- Cleanup();
-}
-
-void VectorDevice::drawPath(const SkDraw& draw, const SkPath& path,
- const SkPaint& paint) {
- if (paint.getPathEffect()) {
- // Apply the path effect forehand.
- SkPath path_modified;
- paint.getFillPath(path, &path_modified);
-
- // Removes the path effect from the temporary SkPaint object.
- SkPaint paint_no_effet(paint);
- paint_no_effet.setPathEffect(NULL)->safeUnref();
-
- // Draw the calculated path.
- drawPath(draw, path_modified, paint_no_effet);
- return;
- }
-
- if (!ApplyPaint(paint)) {
- return;
- }
- HDC dc = getBitmapDC();
- PlatformDeviceWin::LoadPathToDC(dc, path);
- switch (paint.getStyle()) {
- case SkPaint::kFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- DCHECK(res != 0);
- break;
- }
- case SkPaint::kStroke_Style: {
- BOOL res = StrokePath(dc);
- DCHECK(res != 0);
- break;
- }
- case SkPaint::kStrokeAndFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- DCHECK(res != 0);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
- Cleanup();
-}
-
-void VectorDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
- const SkMatrix& matrix, const SkPaint& paint) {
- // Load the temporary matrix. This is what will translate, rotate and resize
- // the bitmap.
- SkMatrix actual_transform(transform_);
- actual_transform.preConcat(matrix);
- LoadTransformToDC(hdc_, actual_transform);
-
- InternalDrawBitmap(bitmap, 0, 0, paint);
-
- // Restore the original matrix.
- LoadTransformToDC(hdc_, transform_);
-}
-
-void VectorDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
- int x, int y, const SkPaint& paint) {
- SkMatrix identity;
- identity.reset();
- LoadTransformToDC(hdc_, identity);
-
- InternalDrawBitmap(bitmap, x, y, paint);
-
- // Restore the original matrix.
- LoadTransformToDC(hdc_, transform_);
-}
-
-void VectorDevice::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.
- NOTREACHED();
-}
-
-void VectorDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
- const SkScalar pos[], SkScalar constY,
- int scalarsPerPos, const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- NOTREACHED();
-}
-
-void VectorDevice::drawTextOnPath(const SkDraw& draw, const void* text,
- size_t len,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- NOTREACHED();
-}
-
-void VectorDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
- int vertexCount,
- const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkXfermode* xmode,
- const uint16_t indices[], int indexCount,
- const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- NOTREACHED();
-}
-
-void VectorDevice::drawDevice(const SkDraw& draw, SkDevice* device, int x,
- int y, const SkPaint& paint) {
- // TODO(maruel): http://b/1183870 Playback the EMF buffer at printer's dpi if
- // it is a vectorial device.
- drawSprite(draw, device->accessBitmap(false), x, y, paint);
-}
-
-bool VectorDevice::ApplyPaint(const SkPaint& paint) {
- // Note: The goal here is to transfert the SkPaint's state to the HDC's state.
- // This function does not execute the SkPaint drawing commands. These should
- // be executed in drawPaint().
-
- SkPaint::Style style = paint.getStyle();
- if (!paint.getAlpha())
- style = SkPaint::kStyleCount;
-
- switch (style) {
- case SkPaint::kFill_Style:
- if (!CreateBrush(true, paint) ||
- !CreatePen(false, paint))
- return false;
- break;
- case SkPaint::kStroke_Style:
- if (!CreateBrush(false, paint) ||
- !CreatePen(true, paint))
- return false;
- break;
- case SkPaint::kStrokeAndFill_Style:
- if (!CreateBrush(true, paint) ||
- !CreatePen(true, paint))
- return false;
- break;
- default:
- if (!CreateBrush(false, paint) ||
- !CreatePen(false, paint))
- return false;
- break;
- }
-
- /*
- getFlags();
- isAntiAlias();
- isDither()
- isLinearText()
- isSubpixelText()
- isUnderlineText()
- isStrikeThruText()
- isFakeBoldText()
- isDevKernText()
- isFilterBitmap()
-
- // Skia's text is not used. This should be fixed.
- getTextAlign()
- getTextScaleX()
- getTextSkewX()
- getTextEncoding()
- getFontMetrics()
- getFontSpacing()
- */
-
- // BUG 1094907: Implement shaders. Shaders currently in use:
- // SkShader::CreateBitmapShader
- // SkGradientShader::CreateRadial
- // SkGradientShader::CreateLinear
- // DCHECK(!paint.getShader());
-
- // http://b/1106647 Implement loopers and mask filter. Looper currently in
- // use:
- // SkBlurDrawLooper is used for shadows.
- // DCHECK(!paint.getLooper());
- // DCHECK(!paint.getMaskFilter());
-
- // http://b/1165900 Implement xfermode.
- // DCHECK(!paint.getXfermode());
-
- // The path effect should be processed before arriving here.
- DCHECK(!paint.getPathEffect());
-
- // These aren't used in the code. Verify this assumption.
- DCHECK(!paint.getColorFilter());
- DCHECK(!paint.getRasterizer());
- // Reuse code to load Win32 Fonts.
- DCHECK(!paint.getTypeface());
- return true;
-}
-
-void VectorDevice::setMatrixClip(const SkMatrix& transform,
- const SkRegion& region) {
- transform_ = transform;
- LoadTransformToDC(hdc_, transform_);
- clip_region_ = region;
- if (!clip_region_.isEmpty())
- LoadClipRegion();
-}
-
-void VectorDevice::drawToHDC(HDC dc, int x, int y, const RECT* src_rect) {
- NOTREACHED();
-}
-
-void VectorDevice::LoadClipRegion() {
- SkMatrix t;
- t.reset();
- LoadClippingRegionToDC(hdc_, clip_region_, t);
-}
-
-bool VectorDevice::CreateBrush(bool use_brush, COLORREF color) {
- DCHECK(previous_brush_ == NULL);
- // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer.
- // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use
- // WHITE_BRUSH instead.
-
- if (!use_brush) {
- // Set the transparency.
- if (0 == SetBkMode(hdc_, TRANSPARENT)) {
- NOTREACHED();
- return false;
- }
-
- // Select the NULL brush.
- previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH));
- return previous_brush_ != NULL;
- }
-
- // Set the opacity.
- if (0 == SetBkMode(hdc_, OPAQUE)) {
- NOTREACHED();
- return false;
- }
-
- // Create and select the brush.
- previous_brush_ = SelectObject(CreateSolidBrush(color));
- return previous_brush_ != NULL;
-}
-
-bool VectorDevice::CreatePen(bool use_pen, COLORREF color, int stroke_width,
- float stroke_miter, DWORD pen_style) {
- DCHECK(previous_pen_ == NULL);
- // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer.
- // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN
- // instead.
-
- // No pen case
- if (!use_pen) {
- previous_pen_ = SelectObject(GetStockObject(NULL_PEN));
- return previous_pen_ != NULL;
- }
-
- // Use the stock pen if the stroke width is 0.
- if (stroke_width == 0) {
- // Create a pen with the right color.
- previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color));
- return previous_pen_ != NULL;
- }
-
- // Load a custom pen.
- LOGBRUSH brush;
- brush.lbStyle = BS_SOLID;
- brush.lbColor = color;
- brush.lbHatch = 0;
- HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL);
- DCHECK(pen != NULL);
- previous_pen_ = SelectObject(pen);
- if (previous_pen_ == NULL)
- return false;
-
- if (!SetMiterLimit(hdc_, stroke_miter, NULL)) {
- NOTREACHED();
- return false;
- }
- return true;
-}
-
-void VectorDevice::Cleanup() {
- if (previous_brush_) {
- HGDIOBJ result = SelectObject(previous_brush_);
- previous_brush_ = NULL;
- if (result) {
- BOOL res = DeleteObject(result);
- DCHECK(res != 0);
- }
- }
- if (previous_pen_) {
- HGDIOBJ result = SelectObject(previous_pen_);
- previous_pen_ = NULL;
- if (result) {
- BOOL res = DeleteObject(result);
- DCHECK(res != 0);
- }
- }
- // Remove any loaded path from the context.
- AbortPath(hdc_);
-}
-
-HGDIOBJ VectorDevice::SelectObject(HGDIOBJ object) {
- HGDIOBJ result = ::SelectObject(hdc_, object);
- DCHECK(result != HGDI_ERROR);
- if (result == HGDI_ERROR)
- return NULL;
- return result;
-}
-
-bool VectorDevice::CreateBrush(bool use_brush, const SkPaint& paint) {
- // Make sure that for transparent color, no brush is used.
- if (paint.getAlpha() == 0) {
- // Test if it ever happen.
- NOTREACHED();
- use_brush = false;
- }
-
- return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor()));
-}
-
-bool VectorDevice::CreatePen(bool use_pen, const SkPaint& paint) {
- // Make sure that for transparent color, no pen is used.
- if (paint.getAlpha() == 0) {
- // Test if it ever happen.
- NOTREACHED();
- use_pen = false;
- }
-
- DWORD pen_style = PS_GEOMETRIC | PS_SOLID;
- switch (paint.getStrokeJoin()) {
- case SkPaint::kMiter_Join:
- // Connects path segments with a sharp join.
- pen_style |= PS_JOIN_MITER;
- break;
- case SkPaint::kRound_Join:
- // Connects path segments with a round join.
- pen_style |= PS_JOIN_ROUND;
- break;
- case SkPaint::kBevel_Join:
- // Connects path segments with a flat bevel join.
- pen_style |= PS_JOIN_BEVEL;
- break;
- default:
- NOTREACHED();
- break;
- }
- switch (paint.getStrokeCap()) {
- case SkPaint::kButt_Cap:
- // Begin/end contours with no extension.
- pen_style |= PS_ENDCAP_FLAT;
- break;
- case SkPaint::kRound_Cap:
- // Begin/end contours with a semi-circle extension.
- pen_style |= PS_ENDCAP_ROUND;
- break;
- case SkPaint::kSquare_Cap:
- // Begin/end contours with a half square extension.
- pen_style |= PS_ENDCAP_SQUARE;
- break;
- default:
- NOTREACHED();
- break;
- }
-
- return CreatePen(use_pen,
- SkColorToCOLORREF(paint.getColor()),
- SkScalarRound(paint.getStrokeWidth()),
- paint.getStrokeMiter(),
- pen_style);
-}
-
-void VectorDevice::InternalDrawBitmap(const SkBitmap& bitmap, int x, int y,
- const SkPaint& paint) {
- uint8 alpha = paint.getAlpha();
- if (alpha == 0)
- return;
-
- bool is_translucent;
- if (alpha != 255) {
- // ApplyPaint expect an opaque color.
- SkPaint tmp_paint(paint);
- tmp_paint.setAlpha(255);
- if (!ApplyPaint(tmp_paint))
- return;
- is_translucent = true;
- } else {
- if (!ApplyPaint(paint))
- return;
- is_translucent = false;
- }
- int src_size_x = bitmap.width();
- int src_size_y = bitmap.height();
- if (!src_size_x || !src_size_y)
- return;
-
- // Create a BMP v4 header that we can serialize.
- BITMAPV4HEADER bitmap_header;
- gfx::CreateBitmapV4Header(src_size_x, src_size_y, &bitmap_header);
- HDC dc = getBitmapDC();
- SkAutoLockPixels lock(bitmap);
- DCHECK_EQ(bitmap.getConfig(), SkBitmap::kARGB_8888_Config);
- const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels());
- if (pixels == NULL) {
- NOTREACHED();
- return;
- }
-
- if (!is_translucent) {
- int row_length = bitmap.rowBytesAsPixels();
- // There is no quick way to determine if an image is opaque.
- for (int y2 = 0; y2 < src_size_y; ++y2) {
- for (int x2 = 0; x2 < src_size_x; ++x2) {
- if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) {
- is_translucent = true;
- y2 = src_size_y;
- break;
- }
- }
- }
- }
-
- BITMAPINFOHEADER hdr;
- gfx::CreateBitmapHeader(src_size_x, src_size_y, &hdr);
- if (is_translucent) {
- // The image must be loaded as a bitmap inside a device context.
- ScopedHDC bitmap_dc(::CreateCompatibleDC(dc));
- void* bits = NULL;
- ScopedBitmap hbitmap(::CreateDIBSection(
- bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS, &bits, NULL, 0));
- memcpy(bits, pixels, bitmap.getSize());
- DCHECK(hbitmap);
- HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap);
- DeleteObject(old_bitmap);
-
- // After some analysis of IE7's behavior, this is the thing to do. I was
- // sure IE7 was doing so kind of bitmasking due to the way translucent image
- // where renderered but after some windbg tracing, it is being done by the
- // printer driver after all (mostly HP printers). IE7 always use AlphaBlend
- // for bitmasked images. The trick seems to switch the stretching mode in
- // what the driver expects.
- DWORD previous_mode = GetStretchBltMode(dc);
- BOOL result = SetStretchBltMode(dc, COLORONCOLOR);
- DCHECK(result);
- // Note that this function expect premultiplied colors (!)
- BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
- result = GdiAlphaBlend(dc,
- x, y, // Destination origin.
- src_size_x, src_size_y, // Destination size.
- bitmap_dc,
- 0, 0, // Source origin.
- src_size_x, src_size_y, // Source size.
- blend_function);
- DCHECK(result);
- result = SetStretchBltMode(dc, previous_mode);
- DCHECK(result);
- } else {
- BOOL result = StretchDIBits(dc,
- x, y, // Destination origin.
- src_size_x, src_size_y,
- 0, 0, // Source origin.
- src_size_x, src_size_y, // Source size.
- pixels,
- reinterpret_cast<const BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS,
- SRCCOPY);
- DCHECK(result);
- }
- Cleanup();
-}
-
-} // namespace gfx
-