Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(573)

Side by Side Diff: skia/ext/bitmap_platform_device_win.cc

Issue 1965453002: Crash on non-rect win clips (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: run it up the flagpole Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698