Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <windows.h> | 5 #include <windows.h> |
| 6 #include <psapi.h> | 6 #include <psapi.h> |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/debug/gdi_debug_util_win.h" | 9 #include "base/debug/gdi_debug_util_win.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 #if !defined(_WIN64) | 47 #if !defined(_WIN64) |
| 48 // If this call fails, we're gonna crash hard. Try to get some useful | 48 // If this call fails, we're gonna crash hard. Try to get some useful |
| 49 // information out before we crash for post-mortem analysis. | 49 // information out before we crash for post-mortem analysis. |
| 50 if (!hbitmap) | 50 if (!hbitmap) |
| 51 base::debug::GDIBitmapAllocFailure(&hdr, shared_section); | 51 base::debug::GDIBitmapAllocFailure(&hdr, shared_section); |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 return hbitmap; | 54 return hbitmap; |
| 55 } | 55 } |
| 56 | 56 |
| 57 struct CubicPoints { | |
| 58 SkPoint p[4]; | |
| 59 }; | |
| 60 typedef std::vector<CubicPoints> CubicPath; | |
| 61 typedef std::vector<CubicPath> CubicPaths; | |
| 62 | |
| 63 bool SkPathToCubicPaths(CubicPaths* paths, const SkPath& skpath) { | |
| 64 paths->clear(); | |
| 65 CubicPath* current_path = NULL; | |
| 66 SkPoint current_points[4]; | |
| 67 CubicPoints points_to_add; | |
| 68 SkPath::Iter iter(skpath, false); | |
| 69 for (SkPath::Verb verb = iter.next(current_points); | |
| 70 verb != SkPath::kDone_Verb; | |
| 71 verb = iter.next(current_points)) { | |
| 72 switch (verb) { | |
| 73 case SkPath::kMove_Verb: { // iter.next returns 1 point | |
| 74 // Ignores it since the point is copied in the next operation. See | |
| 75 // SkPath::Iter::next() for reference. | |
| 76 paths->push_back(CubicPath()); | |
| 77 current_path = &paths->back(); | |
| 78 // Skip point addition. | |
| 79 continue; | |
| 80 } | |
| 81 case SkPath::kLine_Verb: { // iter.next returns 2 points | |
| 82 points_to_add.p[0] = current_points[0]; | |
| 83 points_to_add.p[1] = current_points[0]; | |
| 84 points_to_add.p[2] = current_points[1]; | |
| 85 points_to_add.p[3] = current_points[1]; | |
| 86 break; | |
| 87 } | |
| 88 case SkPath::kQuad_Verb: { // iter.next returns 3 points | |
| 89 points_to_add.p[0] = current_points[0]; | |
| 90 points_to_add.p[1] = current_points[1]; | |
| 91 points_to_add.p[2] = current_points[2]; | |
| 92 points_to_add.p[3] = current_points[2]; | |
| 93 break; | |
| 94 } | |
| 95 case SkPath::kCubic_Verb: { // iter.next returns 4 points | |
| 96 points_to_add.p[0] = current_points[0]; | |
| 97 points_to_add.p[1] = current_points[1]; | |
| 98 points_to_add.p[2] = current_points[2]; | |
| 99 points_to_add.p[3] = current_points[3]; | |
| 100 break; | |
| 101 } | |
| 102 case SkPath::kClose_Verb: { // iter.next returns 1 point (the last point) | |
| 103 paths->push_back(CubicPath()); | |
| 104 current_path = &paths->back(); | |
| 105 continue; | |
| 106 } | |
| 107 default: { | |
| 108 current_path = NULL; | |
| 109 // Will return false. | |
| 110 break; | |
| 111 } | |
| 112 } | |
| 113 SkASSERT(current_path); | |
| 114 if (!current_path) { | |
| 115 paths->clear(); | |
| 116 return false; | |
| 117 } | |
| 118 current_path->push_back(points_to_add); | |
| 119 } | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 bool LoadPathToDC(HDC context, const SkPath& path) { | |
| 124 switch (path.getFillType()) { | |
| 125 case SkPath::kWinding_FillType: { | |
| 126 int res = SetPolyFillMode(context, WINDING); | |
| 127 SkASSERT(res != 0); | |
| 128 break; | |
| 129 } | |
| 130 case SkPath::kEvenOdd_FillType: { | |
| 131 int res = SetPolyFillMode(context, ALTERNATE); | |
| 132 SkASSERT(res != 0); | |
| 133 break; | |
| 134 } | |
| 135 default: { | |
| 136 SkASSERT(false); | |
| 137 break; | |
| 138 } | |
| 139 } | |
| 140 BOOL res = BeginPath(context); | |
| 141 if (!res) { | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 CubicPaths paths; | |
| 146 if (!SkPathToCubicPaths(&paths, path)) | |
| 147 return false; | |
| 148 | |
| 149 std::vector<POINT> points; | |
| 150 for (CubicPaths::const_iterator path(paths.begin()); path != paths.end(); | |
| 151 ++path) { | |
| 152 if (!path->size()) | |
| 153 continue; | |
| 154 points.resize(0); | |
| 155 points.reserve(path->size() * 3 / 4 + 1); | |
| 156 points.push_back(skia::SkPointToPOINT(path->front().p[0])); | |
| 157 for (CubicPath::const_iterator point(path->begin()); point != path->end(); | |
| 158 ++point) { | |
| 159 // Never add point->p[0] | |
| 160 points.push_back(skia::SkPointToPOINT(point->p[1])); | |
| 161 points.push_back(skia::SkPointToPOINT(point->p[2])); | |
| 162 points.push_back(skia::SkPointToPOINT(point->p[3])); | |
| 163 } | |
| 164 SkASSERT((points.size() - 1) % 3 == 0); | |
| 165 // This is slightly inefficient since all straight line and quadratic lines | |
| 166 // are "upgraded" to a cubic line. | |
| 167 // TODO(maruel): http://b/1147346 We should use | |
| 168 // PolyDraw/PolyBezier/Polyline whenever possible. | |
| 169 res = PolyBezier(context, &points.front(), | |
| 170 static_cast<DWORD>(points.size())); | |
| 171 SkASSERT(res != 0); | |
| 172 if (res == 0) | |
| 173 break; | |
| 174 } | |
| 175 if (res == 0) { | |
| 176 // Make sure the path is discarded. | |
| 177 AbortPath(context); | |
| 178 } else { | |
| 179 res = EndPath(context); | |
| 180 SkASSERT(res != 0); | |
| 181 } | |
| 182 return true; | |
| 183 } | |
| 184 | |
| 185 void LoadTransformToDC(HDC dc, const SkMatrix& matrix) { | 57 void LoadTransformToDC(HDC dc, const SkMatrix& matrix) { |
| 186 XFORM xf; | 58 XFORM xf; |
| 187 xf.eM11 = matrix[SkMatrix::kMScaleX]; | 59 xf.eM11 = matrix[SkMatrix::kMScaleX]; |
| 188 xf.eM21 = matrix[SkMatrix::kMSkewX]; | 60 xf.eM21 = matrix[SkMatrix::kMSkewX]; |
| 189 xf.eDx = matrix[SkMatrix::kMTransX]; | 61 xf.eDx = matrix[SkMatrix::kMTransX]; |
| 190 xf.eM12 = matrix[SkMatrix::kMSkewY]; | 62 xf.eM12 = matrix[SkMatrix::kMSkewY]; |
| 191 xf.eM22 = matrix[SkMatrix::kMScaleY]; | 63 xf.eM22 = matrix[SkMatrix::kMScaleY]; |
| 192 xf.eDy = matrix[SkMatrix::kMTransY]; | 64 xf.eDy = matrix[SkMatrix::kMTransY]; |
| 193 SetWorldTransform(dc, &xf); | 65 SetWorldTransform(dc, &xf); |
| 194 } | 66 } |
| 195 | 67 |
| 196 void LoadClippingRegionToDC(HDC context, | 68 void LoadClippingRegionToDC(HDC context, |
| 197 const SkRegion& region, | 69 const SkRegion& region, |
| 198 const SkMatrix& transformation) { | 70 const SkMatrix& transformation) { |
| 199 HRGN hrgn; | 71 HRGN hrgn; |
| 200 if (region.isEmpty()) { | 72 if (region.isEmpty()) { |
| 201 // region can be empty, in which case everything will be clipped. | 73 // region can be empty, in which case everything will be clipped. |
| 202 hrgn = CreateRectRgn(0, 0, 0, 0); | 74 hrgn = CreateRectRgn(0, 0, 0, 0); |
| 203 } else if (region.isRect()) { | 75 } else if (region.isRect()) { |
| 204 // We don't apply transformation, because the translation is already applied | 76 // We don't apply transformation, because the translation is already applied |
| 205 // to the region. | 77 // to the region. |
| 206 hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(region.getBounds())); | 78 hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(region.getBounds())); |
| 207 } else { | 79 } else { |
| 208 // It is complex. | 80 SkASSERT(!"Region clipping is being deprecated; this shouldn't fire."); |
|
reed1
2016/05/09 20:56:38
perhaps repeat the above assignment to hrgn (using
| |
| 209 SkPath path; | |
| 210 region.getBoundaryPath(&path); | |
| 211 // Clip. Note that windows clipping regions are not affected by the | |
| 212 // transform so apply it manually. | |
| 213 // Since the transform is given as the original translation of canvas, we | |
| 214 // should apply it in reverse. | |
| 215 SkMatrix t(transformation); | |
| 216 t.setTranslateX(-t.getTranslateX()); | |
| 217 t.setTranslateY(-t.getTranslateY()); | |
| 218 path.transform(t); | |
| 219 LoadPathToDC(context, path); | |
| 220 hrgn = PathToRegion(context); | |
| 221 } | 81 } |
| 222 int result = SelectClipRgn(context, hrgn); | 82 int result = SelectClipRgn(context, hrgn); |
| 223 SkASSERT(result != ERROR); | 83 SkASSERT(result != ERROR); |
| 224 result = DeleteObject(hrgn); | 84 result = DeleteObject(hrgn); |
| 225 SkASSERT(result != 0); | 85 SkASSERT(result != 0); |
| 226 } | 86 } |
| 227 | 87 |
| 228 } // namespace | 88 } // namespace |
| 229 | 89 |
| 230 namespace skia { | 90 namespace skia { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 int height, | 335 int height, |
| 476 bool is_opaque, | 336 bool is_opaque, |
| 477 HANDLE shared_section, | 337 HANDLE shared_section, |
| 478 OnFailureType failureType) { | 338 OnFailureType failureType) { |
| 479 sk_sp<SkBaseDevice> dev( | 339 sk_sp<SkBaseDevice> dev( |
| 480 BitmapPlatformDevice::Create(width, height, is_opaque, shared_section)); | 340 BitmapPlatformDevice::Create(width, height, is_opaque, shared_section)); |
| 481 return CreateCanvas(dev, failureType); | 341 return CreateCanvas(dev, failureType); |
| 482 } | 342 } |
| 483 | 343 |
| 484 } // namespace skia | 344 } // namespace skia |
| OLD | NEW |