15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/vector_platform_device_emf_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <windows.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/bitmap_platform_device.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/skia_utils_win.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkFontHost.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPathEffect.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkTemplates.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkUtils.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/ports/SkTypeface_win.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace skia {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SkBaseDevice* VectorPlatformDeviceEmf::CreateDevice(
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int width, int height, bool is_opaque, HANDLE shared_section) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_opaque) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(maruel):  http://crbug.com/18382 When restoring a semi-transparent
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // layer, i.e. merging it, we need to rasterize it because GDI doesn't
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // support transparency except for AlphaBlend(). Right now, a
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // BitmapPlatformDevice is created when VectorCanvas think a saveLayers()
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call is being done. The way to save a layer would be to create an
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // EMF-based VectorDevice and have this device registers the drawing. When
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // playing back the device into a bitmap, do it at the printer's dpi instead
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of the layout's dpi (which is much lower).
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return BitmapPlatformDevice::Create(width, height, is_opaque,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        shared_section);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(maruel):  http://crbug.com/18383 Look if it would be worth to
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // increase the resolution by ~10x (any worthy factor) to increase the
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rendering precision (think about printing) while using a relatively
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // low dpi. This happens because we receive float as input but the GDI
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // functions works with integers. The idea is to premultiply the matrix
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with this factor and multiply each SkScalar that are passed to
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SkScalarRound(value) as SkScalarRound(value * 10). Safari is already
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // doing the same for text rendering.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(shared_section);
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SkBaseDevice* device = VectorPlatformDeviceEmf::create(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<HDC>(shared_section), width, height);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return device;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void FillBitmapInfoHeader(int width, int height, BITMAPINFOHEADER* hdr) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biSize = sizeof(BITMAPINFOHEADER);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biWidth = width;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biHeight = -height;  // Minus means top-down bitmap.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biPlanes = 1;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biBitCount = 32;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biCompression = BI_RGB;  // no compression
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biSizeImage = 0;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biXPelsPerMeter = 1;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biYPelsPerMeter = 1;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biClrUsed = 0;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->biClrImportant = 0;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SkBaseDevice* VectorPlatformDeviceEmf::create(HDC dc, int width, int height) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeDC(dc);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Link the SkBitmap to the current selected bitmap in the device context.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HGDIOBJ selected_bitmap = GetCurrentObject(dc, OBJ_BITMAP);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool succeeded = false;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (selected_bitmap != NULL) {
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    BITMAP bitmap_data = {0};
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetObject(selected_bitmap, sizeof(BITMAP), &bitmap_data) ==
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizeof(BITMAP)) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The context has a bitmap attached. Attach our SkBitmap to it.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Warning: If the bitmap gets unselected from the HDC,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // VectorPlatformDeviceEmf has no way to detect this, so the HBITMAP
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // could be released while SkBitmap still has a reference to it. Be
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // cautious.
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (width == bitmap_data.bmWidth && height == bitmap_data.bmHeight) {
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        succeeded = bitmap.installPixels(info, bitmap_data.bmBits,
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         bitmap_data.bmWidthBytes);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!succeeded)
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VectorPlatformDeviceEmf(dc, bitmap);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VectorPlatformDeviceEmf::VectorPlatformDeviceEmf(HDC dc, const SkBitmap& bitmap)
99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : SkBitmapDevice(bitmap),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hdc_(dc),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous_brush_(NULL),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous_pen_(NULL) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform_.reset();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetPlatformDevice(this, this);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VectorPlatformDeviceEmf::~VectorPlatformDeviceEmf() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(previous_brush_ == NULL);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(previous_pen_ == NULL);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HDC VectorPlatformDeviceEmf::BeginPlatformPaint() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hdc_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawPaint(const SkDraw& draw,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const SkPaint& paint) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(maruel):  Bypass the current transformation matrix.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkRect rect;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect.fLeft = 0;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect.fTop = 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect.fRight = SkIntToScalar(width() + 1);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect.fBottom = SkIntToScalar(height() + 1);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drawRect(draw, rect, paint);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawPoints(const SkDraw& draw,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         SkCanvas::PointMode mode,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         size_t count,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkPoint pts[],
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkPaint& paint) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!count)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode == SkCanvas::kPoints_PointMode) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(false);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPaint tmp_paint(paint);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_paint.setStyle(SkPaint::kStroke_Style);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Draw a path instead.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPath path;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (mode) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkCanvas::kLines_PointMode:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (count % 2) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkASSERT(false);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < count / 2; ++i) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path.moveTo(pts[2 * i]);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path.lineTo(pts[2 * i + 1]);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkCanvas::kPolygon_PointMode:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path.moveTo(pts[0]);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 1; i < count; ++i) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path.lineTo(pts[i]);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(false);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Draw the calculated path.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drawPath(draw, path, tmp_paint);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawRect(const SkDraw& draw,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkRect& rect,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkPaint& paint) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_FOR_NODRAW_ANNOTATION(paint);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (paint.getPathEffect()) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Draw a path instead.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path_orginal;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path_orginal.addRect(rect);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Apply the path effect to the rect.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path_modified;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.getFillPath(path_orginal, &path_modified);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Removes the path effect from the temporary SkPaint object.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPaint paint_no_effet(paint);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint_no_effet.setPathEffect(NULL);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Draw the calculated path.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drawPath(draw, path_modified, paint_no_effet);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ApplyPaint(paint)) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC dc = BeginPlatformPaint();
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!Rectangle(dc, SkScalarRoundToInt(rect.fLeft),
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 SkScalarRoundToInt(rect.fTop),
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 SkScalarRoundToInt(rect.fRight),
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 SkScalarRoundToInt(rect.fBottom))) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(false);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndPlatformPaint();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cleanup();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void VectorPlatformDeviceEmf::drawRRect(const SkDraw& draw, const SkRRect& rr,
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const SkPaint& paint) {
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SkPath path;
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  path.addRRect(rr);
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  this->drawPath(draw, path, paint, NULL, true);
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawPath(const SkDraw& draw,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkPath& path,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkPaint& paint,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkMatrix* prePathMatrix,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool pathIsMutable) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_FOR_NODRAW_ANNOTATION(paint);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (paint.getPathEffect()) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Apply the path effect forehand.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path_modified;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.getFillPath(path, &path_modified);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Removes the path effect from the temporary SkPaint object.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPaint paint_no_effet(paint);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint_no_effet.setPathEffect(NULL);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Draw the calculated path.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drawPath(draw, path_modified, paint_no_effet);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ApplyPaint(paint)) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC dc = BeginPlatformPaint();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (PlatformDevice::LoadPathToDC(dc, path)) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (paint.getStyle()) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPaint::kFill_Style: {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BOOL res = StrokeAndFillPath(dc);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkASSERT(res != 0);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPaint::kStroke_Style: {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BOOL res = StrokePath(dc);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkASSERT(res != 0);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPaint::kStrokeAndFill_Style: {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BOOL res = StrokeAndFillPath(dc);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkASSERT(res != 0);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkASSERT(false);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndPlatformPaint();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cleanup();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VectorPlatformDeviceEmf::drawBitmapRect(const SkDraw& draw,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const SkBitmap& bitmap,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const SkRect* src,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const SkRect& dst,
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                             const SkPaint& paint,
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                             SkCanvas::DrawBitmapRectFlags flags) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix    matrix;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkRect      bitmapBounds, tmpSrc, tmpDst;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkBitmap    tmpBitmap;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bitmapBounds.isetWH(bitmap.width(), bitmap.height());
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Compute matrix from the two rectangles
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (src) {
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tmpSrc = *src;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tmpSrc = bitmapBounds;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SkBitmap* bitmapPtr = &bitmap;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // needed (if the src was clipped). No check needed if src==null.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (src) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!bitmapBounds.contains(*src)) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (!tmpSrc.intersect(bitmapBounds)) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return; // nothing to draw
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // recompute dst, based on the smaller tmpSrc
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            matrix.mapRect(&tmpDst, tmpSrc);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // since we may need to clamp to the borders of the src rect within
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // the bitmap, we extract a subset.
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // TODO: make sure this is handled in drawrect and remove it from here.
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkIRect srcIR;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tmpSrc.roundOut(&srcIR);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bitmapPtr = &tmpBitmap;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Since we did an extract, we need to adjust the matrix accordingly
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkScalar dx = 0, dy = 0;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (srcIR.fLeft > 0) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dx = SkIntToScalar(srcIR.fLeft);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (srcIR.fTop > 0) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dy = SkIntToScalar(srcIR.fTop);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (dx || dy) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            matrix.preTranslate(dx, dy);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
318558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    this->drawBitmap(draw, *bitmapPtr, matrix, paint);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawBitmap(const SkDraw& draw,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkBitmap& bitmap,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkMatrix& matrix,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkPaint& paint) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load the temporary matrix. This is what will translate, rotate and resize
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the bitmap.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkMatrix actual_transform(transform_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  actual_transform.preConcat(matrix);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTransformToDC(hdc_, actual_transform);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalDrawBitmap(bitmap, 0, 0, paint);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore the original matrix.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTransformToDC(hdc_, transform_);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawSprite(const SkDraw& draw,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkBitmap& bitmap,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int x, int y,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkPaint& paint) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkMatrix identity;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  identity.reset();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTransformToDC(hdc_, identity);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalDrawBitmap(bitmap, x, y, paint);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore the original matrix.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTransformToDC(hdc_, transform_);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool gdiCanHandleText(const SkPaint& paint) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !paint.getShader() &&
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !paint.getPathEffect() &&
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (SkPaint::kFill_Style == paint.getStyle()) &&
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (255 == paint.getAlpha());
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkGDIFontSetup {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkGDIFontSetup() :
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fHDC(NULL),
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fNewFont(NULL),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fSavedFont(NULL),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fSavedTextColor(0),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fUseGDI(false) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkDEBUGCODE(fUseGDIHasBeenCalled = false;)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SkGDIFontSetup();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can only be called once
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool useGDI(HDC hdc, const SkPaint&);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC      fHDC;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HFONT    fNewFont;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HFONT    fSavedFont;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COLORREF fSavedTextColor;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool     fUseGDI;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkDEBUGCODE(bool fUseGDIHasBeenCalled;)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SkGDIFontSetup::useGDI(HDC hdc, const SkPaint& paint) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(!fUseGDIHasBeenCalled);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkDEBUGCODE(fUseGDIHasBeenCalled = true;)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fUseGDI = gdiCanHandleText(paint);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fUseGDI) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fSavedTextColor = GetTextColor(hdc);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTextColor(hdc, skia::SkColorToCOLORREF(paint.getColor()));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    LOGFONT lf = {0};
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkLOGFONTFromTypeface(paint.getTypeface(), &lf);
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    lf.lfHeight = -SkScalarRoundToInt(paint.getTextSize());
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fNewFont = CreateFontIndirect(&lf);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fSavedFont = (HFONT)::SelectObject(hdc, fNewFont);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fHDC = hdc;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fUseGDI;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkGDIFontSetup::~SkGDIFontSetup() {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fUseGDI) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SelectObject(fHDC, fSavedFont);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::DeleteObject(fNewFont);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetTextColor(fHDC, fSavedTextColor);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkScalar getAscent(const SkPaint& paint) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPaint::FontMetrics fm;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  paint.getFontMetrics(&fm);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fm.fAscent;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return the options int for ExtTextOut. Only valid if the paint's text
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encoding is not UTF8 (in which case ExtTextOut can't be used).
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static UINT getTextOutOptions(const SkPaint& paint) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ETO_GLYPH_INDEX;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(SkPaint::kUTF16_TextEncoding == paint.getTextEncoding());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static SkiaEnsureTypefaceCharactersAccessible
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_skia_ensure_typeface_characters_accessible = NULL;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SK_API void SetSkiaEnsureTypefaceCharactersAccessible(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkiaEnsureTypefaceCharactersAccessible func) {
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This function is supposed to be called once in process life time.
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkASSERT(g_skia_ensure_typeface_characters_accessible == NULL);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_skia_ensure_typeface_characters_accessible = func;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EnsureTypefaceCharactersAccessible(
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SkTypeface& typeface, const wchar_t* text, unsigned int text_length) {
440a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  LOGFONT lf = {0};
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkLOGFONTFromTypeface(&typeface, &lf);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_skia_ensure_typeface_characters_accessible(lf, text, text_length);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool EnsureExtTextOut(HDC hdc, int x, int y, UINT options, const RECT * lprect,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      LPCWSTR text, unsigned int characters, const int * lpDx,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      SkTypeface* const typeface) {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!success) {
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (typeface) {
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureTypefaceCharactersAccessible(*typeface,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         characters);
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!success) {
456a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        LOGFONT lf = {0};
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkLOGFONTFromTypeface(typeface, &lf);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VLOG(1) << "SkFontHost::EnsureTypefaceCharactersAccessible FAILED for "
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                << " FaceName = " << lf.lfFaceName
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                << " and characters: " << base::string16(text, characters);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "ExtTextOut FAILED for default FaceName "
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              << " and characters: " << base::string16(text, characters);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return success;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawText(const SkDraw& draw,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const void* text,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_t byteLength,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       SkScalar x,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       SkScalar y,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const SkPaint& paint) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkGDIFontSetup setup;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool useDrawPath = true;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SkPaint::kUTF8_TextEncoding != paint.getTextEncoding()
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && setup.useGDI(hdc_, paint)) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UINT options = getTextOutOptions(paint);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UINT count = byteLength >> 1;
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    useDrawPath = !EnsureExtTextOut(hdc_, SkScalarRoundToInt(x),
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        SkScalarRoundToInt(y + getAscent(paint)), options, 0,
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const wchar_t*>(text), count, NULL,
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        paint.getTypeface());
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (useDrawPath) {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.getTextPath(text, byteLength, x, y, &path);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drawPath(draw, path, paint);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t size_utf8(const char* text) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SkUTF8_CountUTF8Bytes(text);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t size_utf16(const char* text) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t c = *reinterpret_cast<const uint16_t*>(text);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SkUTF16_IsHighSurrogate(c) ? 4 : 2;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t size_glyphid(const char* text) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 2;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const void* text,
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          size_t len,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const SkScalar pos[],
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          SkScalar constY,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int scalarsPerPos,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const SkPaint& paint) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkGDIFontSetup setup;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool useDrawText = true;
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (scalarsPerPos == 2 && len >= 2 &&
520a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SkPaint::kUTF8_TextEncoding != paint.getTextEncoding() &&
521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      setup.useGDI(hdc_, paint)) {
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int startX = SkScalarRoundToInt(pos[0]);
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int startY = SkScalarRoundToInt(pos[1] + getAscent(paint));
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int count = len >> 1;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkAutoSTMalloc<64, INT> storage(count);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INT* advances = storage.get();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < count - 1; ++i) {
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      advances[i] = SkScalarRoundToInt(pos[2] - pos[0]);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos += 2;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
531a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    advances[count - 1] = 0;
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    useDrawText = !EnsureExtTextOut(hdc_, startX, startY,
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        getTextOutOptions(paint), 0, reinterpret_cast<const wchar_t*>(text),
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        count, advances, paint.getTypeface());
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (useDrawText) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t (*bytesPerCodePoint)(const char*);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (paint.getTextEncoding()) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kUTF8_TextEncoding:
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytesPerCodePoint = size_utf8;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kUTF16_TextEncoding:
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytesPerCodePoint = size_utf16;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytesPerCodePoint = size_glyphid;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* curr = reinterpret_cast<const char*>(text);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* stop = curr + len;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (curr < stop) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkScalar y = (1 == scalarsPerPos) ? constY : pos[1];
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t bytes = bytesPerCodePoint(curr);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drawText(draw, curr, bytes, pos[0], y, paint);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr += bytes;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos += scalarsPerPos;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawTextOnPath(const SkDraw& draw,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const void* text,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             size_t len,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const SkPath& path,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const SkMatrix* matrix,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const SkPaint& paint) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function isn't used in the code. Verify this assumption.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(false);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawVertices(const SkDraw& draw,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SkCanvas::VertexMode vmode,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int vertexCount,
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const SkPoint vertices[],
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const SkPoint texs[],
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const SkColor colors[],
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SkXfermode* xmode,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const uint16_t indices[],
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int indexCount,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const SkPaint& paint) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function isn't used in the code. Verify this assumption.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(false);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::drawDevice(const SkDraw& draw,
589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                         SkBaseDevice* device,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int x,
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int y,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const SkPaint& paint) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(maruel):  http://b/1183870 Playback the EMF buffer at printer's dpi if
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it is a vectorial device.
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drawSprite(draw, device->accessBitmap(false), x, y, paint);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorPlatformDeviceEmf::ApplyPaint(const SkPaint& paint) {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: The goal here is to transfert the SkPaint's state to the HDC's state.
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function does not execute the SkPaint drawing commands. These should
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be executed in drawPaint().
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPaint::Style style = paint.getStyle();
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!paint.getAlpha())
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      style = (SkPaint::Style) SkPaint::kStyleCount;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (style) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kFill_Style:
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CreateBrush(true, paint) ||
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !CreatePen(false, paint))
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kStroke_Style:
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CreateBrush(false, paint) ||
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !CreatePen(true, paint))
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kStrokeAndFill_Style:
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CreateBrush(true, paint) ||
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !CreatePen(true, paint))
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CreateBrush(false, paint) ||
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !CreatePen(false, paint))
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getFlags();
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isAntiAlias();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isDither()
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isLinearText()
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isSubpixelText()
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isUnderlineText()
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isStrikeThruText()
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isFakeBoldText()
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isDevKernText()
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isFilterBitmap()
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skia's text is not used. This should be fixed.
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getTextAlign()
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getTextScaleX()
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getTextSkewX()
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getTextEncoding()
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getFontMetrics()
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getFontSpacing()
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BUG 1094907: Implement shaders. Shaders currently in use:
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  SkShader::CreateBitmapShader
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  SkGradientShader::CreateRadial
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  SkGradientShader::CreateLinear
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SkASSERT(!paint.getShader());
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://b/1106647 Implement loopers and mask filter. Looper currently in
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use:
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SkBlurDrawLooper is used for shadows.
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SkASSERT(!paint.getLooper());
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SkASSERT(!paint.getMaskFilter());
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://b/1165900 Implement xfermode.
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SkASSERT(!paint.getXfermode());
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path effect should be processed before arriving here.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(!paint.getPathEffect());
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This isn't used in the code. Verify this assumption.
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(!paint.getRasterizer());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reuse code to load Win32 Fonts.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::setMatrixClip(const SkMatrix& transform,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const SkRegion& region,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const SkClipStack&) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform_ = transform;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadTransformToDC(hdc_, transform_);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clip_region_ = region;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!clip_region_.isEmpty())
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadClipRegion();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::DrawToNativeContext(HDC dc, int x, int y,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const RECT* src_rect) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(false);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::LoadClipRegion() {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkMatrix t;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.reset();
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadClippingRegionToDC(hdc_, clip_region_, t);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
696effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSkBaseDevice* VectorPlatformDeviceEmf::onCreateDevice(const SkImageInfo& info,
697effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                      Usage /*usage*/) {
698116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SkASSERT(info.colorType() == kN32_SkColorType);
699effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return VectorPlatformDeviceEmf::CreateDevice(
700effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      info.width(), info.height(), info.isOpaque(), NULL);
701effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush, COLORREF color) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(previous_brush_ == NULL);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WHITE_BRUSH instead.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!use_brush) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the transparency.
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 == SetBkMode(hdc_, TRANSPARENT)) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(false);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Select the NULL brush.
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return previous_brush_ != NULL;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the opacity.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == SetBkMode(hdc_, OPAQUE)) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(false);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create and select the brush.
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_brush_ = SelectObject(CreateSolidBrush(color));
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return previous_brush_ != NULL;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorPlatformDeviceEmf::CreatePen(bool use_pen,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        COLORREF color,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int stroke_width,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        float stroke_miter,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        DWORD pen_style) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(previous_pen_ == NULL);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead.
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No pen case
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!use_pen) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_pen_ = SelectObject(GetStockObject(NULL_PEN));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return previous_pen_ != NULL;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the stock pen if the stroke width is 0.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stroke_width == 0) {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a pen with the right color.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color));
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return previous_pen_ != NULL;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load a custom pen.
756a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  LOGBRUSH brush = {0};
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  brush.lbStyle = BS_SOLID;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  brush.lbColor = color;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  brush.lbHatch = 0;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(pen != NULL);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_pen_ = SelectObject(pen);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_pen_ == NULL)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SetMiterLimit(hdc_, stroke_miter, NULL)) {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(false);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::Cleanup() {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_brush_) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HGDIOBJ result = SelectObject(previous_brush_);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_brush_ = NULL;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL res = DeleteObject(result);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(res != 0);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_pen_) {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HGDIOBJ result = SelectObject(previous_pen_);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_pen_ = NULL;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BOOL res = DeleteObject(result);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(res != 0);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove any loaded path from the context.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AbortPath(hdc_);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HGDIOBJ VectorPlatformDeviceEmf::SelectObject(HGDIOBJ object) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HGDIOBJ result = ::SelectObject(hdc_, object);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(result != HGDI_ERROR);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == HGDI_ERROR)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush,
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const SkPaint& paint) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that for transparent color, no brush is used.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (paint.getAlpha() == 0) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    use_brush = false;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor()));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorPlatformDeviceEmf::CreatePen(bool use_pen, const SkPaint& paint) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that for transparent color, no pen is used.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (paint.getAlpha() == 0) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    use_pen = false;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD pen_style = PS_GEOMETRIC | PS_SOLID;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (paint.getStrokeJoin()) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kMiter_Join:
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Connects path segments with a sharp join.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_JOIN_MITER;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kRound_Join:
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Connects path segments with a round join.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_JOIN_ROUND;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kBevel_Join:
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Connects path segments with a flat bevel join.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_JOIN_BEVEL;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(false);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (paint.getStrokeCap()) {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kButt_Cap:
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Begin/end contours with no extension.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_ENDCAP_FLAT;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kRound_Cap:
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Begin/end contours with a semi-circle extension.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_ENDCAP_ROUND;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPaint::kSquare_Cap:
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Begin/end contours with a half square extension.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pen_style |= PS_ENDCAP_SQUARE;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(false);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreatePen(use_pen,
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SkColorToCOLORREF(paint.getColor()),
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   SkScalarRoundToInt(paint.getStrokeWidth()),
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   paint.getStrokeMiter(),
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   pen_style);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VectorPlatformDeviceEmf::InternalDrawBitmap(const SkBitmap& bitmap,
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 int x, int y,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const SkPaint& paint) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char alpha = paint.getAlpha();
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alpha == 0)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_translucent;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alpha != 255) {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ApplyPaint expect an opaque color.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPaint tmp_paint(paint);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp_paint.setAlpha(255);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ApplyPaint(tmp_paint))
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_translucent = true;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ApplyPaint(paint))
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_translucent = false;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int src_size_x = bitmap.width();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int src_size_y = bitmap.height();
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!src_size_x || !src_size_y)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a BMP v4 header that we can serialize. We use the shared "V3"
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fillter to fill the stardard items, then add in the "V4" stuff we want.
888a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BITMAPV4HEADER bitmap_header = {0};
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillBitmapInfoHeader(src_size_x, src_size_y,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       reinterpret_cast<BITMAPINFOHEADER*>(&bitmap_header));
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_header.bV4Size = sizeof(BITMAPV4HEADER);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_header.bV4RedMask   = 0x00ff0000;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_header.bV4GreenMask = 0x0000ff00;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_header.bV4BlueMask  = 0x000000ff;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_header.bV4AlphaMask = 0xff000000;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkAutoLockPixels lock(bitmap);
898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SkASSERT(bitmap.colorType() == kN32_SkColorType);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels());
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pixels == NULL) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(false);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_translucent) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int row_length = bitmap.rowBytesAsPixels();
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no quick way to determine if an image is opaque.
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y2 = 0; y2 < src_size_y; ++y2) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int x2 = 0; x2 < src_size_x; ++x2) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_translucent = true;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          y2 = src_size_y;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC dc = BeginPlatformPaint();
920a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BITMAPINFOHEADER hdr = {0};
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillBitmapInfoHeader(src_size_x, src_size_y, &hdr);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_translucent) {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The image must be loaded as a bitmap inside a device context.
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HDC bitmap_dc = ::CreateCompatibleDC(dc);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* bits = NULL;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HBITMAP hbitmap = ::CreateDIBSection(
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr),
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DIB_RGB_COLORS, &bits, NULL, 0);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // static cast to a char so we can do byte ptr arithmatic to
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // get the offset.
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char* dest_buffer = static_cast<unsigned char *>(bits);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We will copy row by row to avoid having to worry about
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the row strides being different.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int dest_row_size = hdr.biBitCount / 8 * hdr.biWidth;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int row = 0; row < bitmap.height(); ++row) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int dest_offset = row * dest_row_size;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pixels_offset in terms of pixel count.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int src_offset = row * bitmap.rowBytesAsPixels();
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(dest_buffer + dest_offset, pixels + src_offset, dest_row_size);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(hbitmap);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After some analysis of IE7's behavior, this is the thing to do. I was
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure IE7 was doing so kind of bitmasking due to the way translucent image
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // where renderered but after some windbg tracing, it is being done by the
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // printer driver after all (mostly HP printers). IE7 always use AlphaBlend
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for bitmasked images. The trick seems to switch the stretching mode in
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // what the driver expects.
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD previous_mode = GetStretchBltMode(dc);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BOOL result = SetStretchBltMode(dc, COLORONCOLOR);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(result);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that this function expect premultiplied colors (!)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = GdiAlphaBlend(dc,
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           x, y,  // Destination origin.
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           src_size_x, src_size_y,  // Destination size.
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bitmap_dc,
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0, 0,  // Source origin.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           src_size_x, src_size_y,  // Source size.
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           blend_function);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(result);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = SetStretchBltMode(dc, previous_mode);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(result);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SelectObject(bitmap_dc, static_cast<HBITMAP>(old_bitmap));
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteObject(hbitmap);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteDC(bitmap_dc);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nCopied = StretchDIBits(dc,
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                x, y,  // Destination origin.
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                src_size_x, src_size_y,
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                0, 0,  // Source origin.
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                src_size_x, src_size_y,  // Source size.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                pixels,
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                reinterpret_cast<const BITMAPINFO*>(&hdr),
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                DIB_RGB_COLORS,
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SRCCOPY);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndPlatformPaint();
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cleanup();
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace skia
987