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/platform_device.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/skia_utils_win.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkMatrix.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPath.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkRegion.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkUtils.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace skia {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeDC(HDC context) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enables world transformation.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the GM_ADVANCED graphics mode is set, GDI always draws arcs in the
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // counterclockwise direction in logical space. This is equivalent to the
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // statement that, in the GM_ADVANCED graphics mode, both arc control points
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and arcs themselves fully respect the device context's world-to-device
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transformation.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL res = SetGraphicsMode(context, GM_ADVANCED);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enables dithering.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetStretchBltMode(context, HALFTONE);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As per SetStretchBltMode() documentation, SetBrushOrgEx() must be called
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // right after.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetBrushOrgEx(context, 0, 0, NULL);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets up default orientation.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetArcDirection(context, AD_CLOCKWISE);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets up default colors.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetBkColor(context, RGB(255, 255, 255));
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != CLR_INVALID);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetTextColor(context, RGB(0, 0, 0));
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != CLR_INVALID);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetDCBrushColor(context, RGB(255, 255, 255));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != CLR_INVALID);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetDCPenColor(context, RGB(0, 0, 0));
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != CLR_INVALID);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets up default transparency.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetBkMode(context, OPAQUE);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = SetROP2(context, R2_COPYPEN);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(res != 0);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PlatformSurface PlatformDevice::BeginPlatformPaint() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformDevice::EndPlatformPaint() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't clear the DC here since it will be likely to be used again.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flushing will be done in onAccessBitmap.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformDevice::DrawToNativeContext(PlatformSurface surface, int x, int y,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const PlatformRect* src_rect) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PlatformDevice::LoadPathToDC(HDC context, const SkPath& path) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (path.getFillType()) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPath::kWinding_FillType: {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int res = SetPolyFillMode(context, WINDING);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(res != 0);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SkPath::kEvenOdd_FillType: {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int res = SetPolyFillMode(context, ALTERNATE);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(res != 0);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default: {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkASSERT(false);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL res = BeginPath(context);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!res) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CubicPaths paths;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SkPathToCubicPaths(&paths, path))
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<POINT> points;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CubicPaths::const_iterator path(paths.begin()); path != paths.end();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++path) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!path->size())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    points.resize(0);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    points.reserve(path->size() * 3 / 4 + 1);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    points.push_back(SkPointToPOINT(path->front().p[0]));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (CubicPath::const_iterator point(path->begin()); point != path->end();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++point) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Never add point->p[0]
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      points.push_back(SkPointToPOINT(point->p[1]));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      points.push_back(SkPointToPOINT(point->p[2]));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      points.push_back(SkPointToPOINT(point->p[3]));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT((points.size() - 1) % 3 == 0);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is slightly inefficient since all straight line and quadratic lines
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // are "upgraded" to a cubic line.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(maruel):  http://b/1147346 We should use
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // PolyDraw/PolyBezier/Polyline whenever possible.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = PolyBezier(context, &points.front(),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     static_cast<DWORD>(points.size()));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(res != 0);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (res == 0)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (res == 0) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the path is discarded.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AbortPath(context);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = EndPath(context);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(res != 0);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformDevice::LoadTransformToDC(HDC dc, const SkMatrix& matrix) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFORM xf;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eM11 = matrix[SkMatrix::kMScaleX];
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eM21 = matrix[SkMatrix::kMSkewX];
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eDx = matrix[SkMatrix::kMTransX];
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eM12 = matrix[SkMatrix::kMSkewY];
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eM22 = matrix[SkMatrix::kMScaleY];
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xf.eDy = matrix[SkMatrix::kMTransY];
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetWorldTransform(dc, &xf);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PlatformDevice::SkPathToCubicPaths(CubicPaths* paths,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const SkPath& skpath) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  paths->clear();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CubicPath* current_path = NULL;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPoint current_points[4];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CubicPoints points_to_add;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkPath::Iter iter(skpath, false);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SkPath::Verb verb = iter.next(current_points);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       verb != SkPath::kDone_Verb;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       verb = iter.next(current_points)) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (verb) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPath::kMove_Verb: {  // iter.next returns 1 point
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Ignores it since the point is copied in the next operation. See
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SkPath::Iter::next() for reference.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        paths->push_back(CubicPath());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_path = &paths->back();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Skip point addition.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPath::kLine_Verb: {  // iter.next returns 2 points
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[0] = current_points[0];
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[1] = current_points[0];
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[2] = current_points[1];
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[3] = current_points[1];
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPath::kQuad_Verb: {  // iter.next returns 3 points
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[0] = current_points[0];
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[1] = current_points[1];
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[2] = current_points[2];
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[3] = current_points[2];
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPath::kCubic_Verb: {  // iter.next returns 4 points
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[0] = current_points[0];
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[1] = current_points[1];
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[2] = current_points[2];
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points_to_add.p[3] = current_points[3];
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SkPath::kClose_Verb: {  // iter.next returns 1 point (the last point)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        paths->push_back(CubicPath());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_path = &paths->back();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default: {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_path = NULL;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Will return false.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(current_path);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!current_path) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paths->clear();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_path->push_back(points_to_add);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PlatformDevice::LoadClippingRegionToDC(HDC context,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const SkRegion& region,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const SkMatrix& transformation) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRGN hrgn;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (region.isEmpty()) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // region can be empty, in which case everything will be clipped.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hrgn = CreateRectRgn(0, 0, 0, 0);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (region.isRect()) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't apply transformation, because the translation is already applied
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to the region.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hrgn = CreateRectRgnIndirect(&SkIRectToRECT(region.getBounds()));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It is complex.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    region.getBoundaryPath(&path);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clip. Note that windows clipping regions are not affected by the
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // transform so apply it manually.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since the transform is given as the original translation of canvas, we
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should apply it in reverse.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkMatrix t(transformation);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t.setTranslateX(-t.getTranslateX());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t.setTranslateY(-t.getTranslateY());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path.transform(t);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadPathToDC(context, path);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hrgn = PathToRegion(context);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = SelectClipRgn(context, hrgn);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(result != ERROR);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = DeleteObject(hrgn);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkASSERT(result != 0);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace skia
238