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