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

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

Issue 14903: Reverting 7318. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years 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 | Annotate | Revision Log
« no previous file with comments | « skia/ext/vector_device.h ('k') | 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "skia/ext/vector_device.h" 5 #include "skia/ext/vector_device.h"
6 6
7 #include "base/gfx/gdi_util.h" 7 #include "base/gfx/gdi_util.h"
8 #include "base/logging.h"
9 #include "base/scoped_handle.h"
10 #include "skia/ext/skia_utils_win.h" 8 #include "skia/ext/skia_utils_win.h"
11 9
12 #include "SkUtils.h" 10 #include "SkUtils.h"
13 11
14 namespace skia { 12 namespace skia {
15 13
16 VectorDevice* VectorDevice::create(HDC dc, int width, int height) { 14 VectorDevice* VectorDevice::create(HDC dc, int width, int height) {
17 InitializeDC(dc); 15 InitializeDC(dc);
18 16
19 // Link the SkBitmap to the current selected bitmap in the device context. 17 // Link the SkBitmap to the current selected bitmap in the device context.
(...skipping 28 matching lines...) Expand all
48 46
49 VectorDevice::VectorDevice(HDC dc, const SkBitmap& bitmap) 47 VectorDevice::VectorDevice(HDC dc, const SkBitmap& bitmap)
50 : PlatformDeviceWin(bitmap), 48 : PlatformDeviceWin(bitmap),
51 hdc_(dc), 49 hdc_(dc),
52 previous_brush_(NULL), 50 previous_brush_(NULL),
53 previous_pen_(NULL) { 51 previous_pen_(NULL) {
54 transform_.reset(); 52 transform_.reset();
55 } 53 }
56 54
57 VectorDevice::~VectorDevice() { 55 VectorDevice::~VectorDevice() {
58 DCHECK(previous_brush_ == NULL); 56 SkASSERT(previous_brush_ == NULL);
59 DCHECK(previous_pen_ == NULL); 57 SkASSERT(previous_pen_ == NULL);
60 } 58 }
61 59
62 60
63 void VectorDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { 61 void VectorDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
64 // TODO(maruel): Bypass the current transformation matrix. 62 // TODO(maruel): Bypass the current transformation matrix.
65 SkRect rect; 63 SkRect rect;
66 rect.fLeft = 0; 64 rect.fLeft = 0;
67 rect.fTop = 0; 65 rect.fTop = 0;
68 rect.fRight = SkIntToScalar(width() + 1); 66 rect.fRight = SkIntToScalar(width() + 1);
69 rect.fBottom = SkIntToScalar(height() + 1); 67 rect.fBottom = SkIntToScalar(height() + 1);
70 drawRect(draw, rect, paint); 68 drawRect(draw, rect, paint);
71 } 69 }
72 70
73 void VectorDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, 71 void VectorDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
74 size_t count, const SkPoint pts[], 72 size_t count, const SkPoint pts[],
75 const SkPaint& paint) { 73 const SkPaint& paint) {
76 if (!count) 74 if (!count)
77 return; 75 return;
78 76
79 if (mode == SkCanvas::kPoints_PointMode) { 77 if (mode == SkCanvas::kPoints_PointMode) {
80 NOTREACHED(); 78 SkASSERT(false);
81 return; 79 return;
82 } 80 }
83 81
84 SkPaint tmp_paint(paint); 82 SkPaint tmp_paint(paint);
85 tmp_paint.setStyle(SkPaint::kStroke_Style); 83 tmp_paint.setStyle(SkPaint::kStroke_Style);
86 84
87 // Draw a path instead. 85 // Draw a path instead.
88 SkPath path; 86 SkPath path;
89 switch (mode) { 87 switch (mode) {
90 case SkCanvas::kLines_PointMode: 88 case SkCanvas::kLines_PointMode:
91 if (count % 2) { 89 if (count % 2) {
92 NOTREACHED(); 90 SkASSERT(false);
93 return; 91 return;
94 } 92 }
95 for (size_t i = 0; i < count / 2; ++i) { 93 for (size_t i = 0; i < count / 2; ++i) {
96 path.moveTo(pts[2 * i]); 94 path.moveTo(pts[2 * i]);
97 path.lineTo(pts[2 * i + 1]); 95 path.lineTo(pts[2 * i + 1]);
98 } 96 }
99 break; 97 break;
100 case SkCanvas::kPolygon_PointMode: 98 case SkCanvas::kPolygon_PointMode:
101 path.moveTo(pts[0]); 99 path.moveTo(pts[0]);
102 for (size_t i = 1; i < count; ++i) { 100 for (size_t i = 1; i < count; ++i) {
103 path.lineTo(pts[i]); 101 path.lineTo(pts[i]);
104 } 102 }
105 break; 103 break;
106 default: 104 default:
107 NOTREACHED(); 105 SkASSERT(false);
108 return; 106 return;
109 } 107 }
110 // Draw the calculated path. 108 // Draw the calculated path.
111 drawPath(draw, path, tmp_paint); 109 drawPath(draw, path, tmp_paint);
112 } 110 }
113 111
114 void VectorDevice::drawRect(const SkDraw& draw, const SkRect& rect, 112 void VectorDevice::drawRect(const SkDraw& draw, const SkRect& rect,
115 const SkPaint& paint) { 113 const SkPaint& paint) {
116 if (paint.getPathEffect()) { 114 if (paint.getPathEffect()) {
117 // Draw a path instead. 115 // Draw a path instead.
(...skipping 14 matching lines...) Expand all
132 } 130 }
133 131
134 if (!ApplyPaint(paint)) { 132 if (!ApplyPaint(paint)) {
135 return; 133 return;
136 } 134 }
137 HDC dc = getBitmapDC(); 135 HDC dc = getBitmapDC();
138 if (!Rectangle(dc, SkScalarRound(rect.fLeft), 136 if (!Rectangle(dc, SkScalarRound(rect.fLeft),
139 SkScalarRound(rect.fTop), 137 SkScalarRound(rect.fTop),
140 SkScalarRound(rect.fRight), 138 SkScalarRound(rect.fRight),
141 SkScalarRound(rect.fBottom))) { 139 SkScalarRound(rect.fBottom))) {
142 NOTREACHED(); 140 SkASSERT(false);
143 } 141 }
144 Cleanup(); 142 Cleanup();
145 } 143 }
146 144
147 void VectorDevice::drawPath(const SkDraw& draw, const SkPath& path, 145 void VectorDevice::drawPath(const SkDraw& draw, const SkPath& path,
148 const SkPaint& paint) { 146 const SkPaint& paint) {
149 if (paint.getPathEffect()) { 147 if (paint.getPathEffect()) {
150 // Apply the path effect forehand. 148 // Apply the path effect forehand.
151 SkPath path_modified; 149 SkPath path_modified;
152 paint.getFillPath(path, &path_modified); 150 paint.getFillPath(path, &path_modified);
153 151
154 // Removes the path effect from the temporary SkPaint object. 152 // Removes the path effect from the temporary SkPaint object.
155 SkPaint paint_no_effet(paint); 153 SkPaint paint_no_effet(paint);
156 paint_no_effet.setPathEffect(NULL)->safeUnref(); 154 paint_no_effet.setPathEffect(NULL)->safeUnref();
157 155
158 // Draw the calculated path. 156 // Draw the calculated path.
159 drawPath(draw, path_modified, paint_no_effet); 157 drawPath(draw, path_modified, paint_no_effet);
160 return; 158 return;
161 } 159 }
162 160
163 if (!ApplyPaint(paint)) { 161 if (!ApplyPaint(paint)) {
164 return; 162 return;
165 } 163 }
166 HDC dc = getBitmapDC(); 164 HDC dc = getBitmapDC();
167 PlatformDeviceWin::LoadPathToDC(dc, path); 165 PlatformDeviceWin::LoadPathToDC(dc, path);
168 switch (paint.getStyle()) { 166 switch (paint.getStyle()) {
169 case SkPaint::kFill_Style: { 167 case SkPaint::kFill_Style: {
170 BOOL res = StrokeAndFillPath(dc); 168 BOOL res = StrokeAndFillPath(dc);
171 DCHECK(res != 0); 169 SkASSERT(res != 0);
172 break; 170 break;
173 } 171 }
174 case SkPaint::kStroke_Style: { 172 case SkPaint::kStroke_Style: {
175 BOOL res = StrokePath(dc); 173 BOOL res = StrokePath(dc);
176 DCHECK(res != 0); 174 SkASSERT(res != 0);
177 break; 175 break;
178 } 176 }
179 case SkPaint::kStrokeAndFill_Style: { 177 case SkPaint::kStrokeAndFill_Style: {
180 BOOL res = StrokeAndFillPath(dc); 178 BOOL res = StrokeAndFillPath(dc);
181 DCHECK(res != 0); 179 SkASSERT(res != 0);
182 break; 180 break;
183 } 181 }
184 default: 182 default:
185 NOTREACHED(); 183 SkASSERT(false);
186 break; 184 break;
187 } 185 }
188 Cleanup(); 186 Cleanup();
189 } 187 }
190 188
191 void VectorDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, 189 void VectorDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
192 const SkMatrix& matrix, const SkPaint& paint) { 190 const SkMatrix& matrix, const SkPaint& paint) {
193 // Load the temporary matrix. This is what will translate, rotate and resize 191 // Load the temporary matrix. This is what will translate, rotate and resize
194 // the bitmap. 192 // the bitmap.
195 SkMatrix actual_transform(transform_); 193 SkMatrix actual_transform(transform_);
(...skipping 14 matching lines...) Expand all
210 208
211 InternalDrawBitmap(bitmap, x, y, paint); 209 InternalDrawBitmap(bitmap, x, y, paint);
212 210
213 // Restore the original matrix. 211 // Restore the original matrix.
214 LoadTransformToDC(hdc_, transform_); 212 LoadTransformToDC(hdc_, transform_);
215 } 213 }
216 214
217 void VectorDevice::drawText(const SkDraw& draw, const void* text, size_t byteLen gth, 215 void VectorDevice::drawText(const SkDraw& draw, const void* text, size_t byteLen gth,
218 SkScalar x, SkScalar y, const SkPaint& paint) { 216 SkScalar x, SkScalar y, const SkPaint& paint) {
219 // This function isn't used in the code. Verify this assumption. 217 // This function isn't used in the code. Verify this assumption.
220 NOTREACHED(); 218 SkASSERT(false);
221 } 219 }
222 220
223 void VectorDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, 221 void VectorDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
224 const SkScalar pos[], SkScalar constY, 222 const SkScalar pos[], SkScalar constY,
225 int scalarsPerPos, const SkPaint& paint) { 223 int scalarsPerPos, const SkPaint& paint) {
226 // This function isn't used in the code. Verify this assumption. 224 // This function isn't used in the code. Verify this assumption.
227 NOTREACHED(); 225 SkASSERT(false);
228 } 226 }
229 227
230 void VectorDevice::drawTextOnPath(const SkDraw& draw, const void* text, 228 void VectorDevice::drawTextOnPath(const SkDraw& draw, const void* text,
231 size_t len, 229 size_t len,
232 const SkPath& path, const SkMatrix* matrix, 230 const SkPath& path, const SkMatrix* matrix,
233 const SkPaint& paint) { 231 const SkPaint& paint) {
234 // This function isn't used in the code. Verify this assumption. 232 // This function isn't used in the code. Verify this assumption.
235 NOTREACHED(); 233 SkASSERT(false);
236 } 234 }
237 235
238 void VectorDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, 236 void VectorDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
239 int vertexCount, 237 int vertexCount,
240 const SkPoint vertices[], const SkPoint texs[], 238 const SkPoint vertices[], const SkPoint texs[],
241 const SkColor colors[], SkXfermode* xmode, 239 const SkColor colors[], SkXfermode* xmode,
242 const uint16_t indices[], int indexCount, 240 const uint16_t indices[], int indexCount,
243 const SkPaint& paint) { 241 const SkPaint& paint) {
244 // This function isn't used in the code. Verify this assumption. 242 // This function isn't used in the code. Verify this assumption.
245 NOTREACHED(); 243 SkASSERT(false);
246 } 244 }
247 245
248 void VectorDevice::drawDevice(const SkDraw& draw, SkDevice* device, int x, 246 void VectorDevice::drawDevice(const SkDraw& draw, SkDevice* device, int x,
249 int y, const SkPaint& paint) { 247 int y, const SkPaint& paint) {
250 // TODO(maruel): http://b/1183870 Playback the EMF buffer at printer's dpi if 248 // TODO(maruel): http://b/1183870 Playback the EMF buffer at printer's dpi if
251 // it is a vectorial device. 249 // it is a vectorial device.
252 drawSprite(draw, device->accessBitmap(false), x, y, paint); 250 drawSprite(draw, device->accessBitmap(false), x, y, paint);
253 } 251 }
254 252
255 bool VectorDevice::ApplyPaint(const SkPaint& paint) { 253 bool VectorDevice::ApplyPaint(const SkPaint& paint) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 getTextSkewX() 300 getTextSkewX()
303 getTextEncoding() 301 getTextEncoding()
304 getFontMetrics() 302 getFontMetrics()
305 getFontSpacing() 303 getFontSpacing()
306 */ 304 */
307 305
308 // BUG 1094907: Implement shaders. Shaders currently in use: 306 // BUG 1094907: Implement shaders. Shaders currently in use:
309 // SkShader::CreateBitmapShader 307 // SkShader::CreateBitmapShader
310 // SkGradientShader::CreateRadial 308 // SkGradientShader::CreateRadial
311 // SkGradientShader::CreateLinear 309 // SkGradientShader::CreateLinear
312 // DCHECK(!paint.getShader()); 310 // SkASSERT(!paint.getShader());
313 311
314 // http://b/1106647 Implement loopers and mask filter. Looper currently in 312 // http://b/1106647 Implement loopers and mask filter. Looper currently in
315 // use: 313 // use:
316 // SkBlurDrawLooper is used for shadows. 314 // SkBlurDrawLooper is used for shadows.
317 // DCHECK(!paint.getLooper()); 315 // SkASSERT(!paint.getLooper());
318 // DCHECK(!paint.getMaskFilter()); 316 // SkASSERT(!paint.getMaskFilter());
319 317
320 // http://b/1165900 Implement xfermode. 318 // http://b/1165900 Implement xfermode.
321 // DCHECK(!paint.getXfermode()); 319 // SkASSERT(!paint.getXfermode());
322 320
323 // The path effect should be processed before arriving here. 321 // The path effect should be processed before arriving here.
324 DCHECK(!paint.getPathEffect()); 322 SkASSERT(!paint.getPathEffect());
325 323
326 // These aren't used in the code. Verify this assumption. 324 // These aren't used in the code. Verify this assumption.
327 DCHECK(!paint.getColorFilter()); 325 SkASSERT(!paint.getColorFilter());
328 DCHECK(!paint.getRasterizer()); 326 SkASSERT(!paint.getRasterizer());
329 // Reuse code to load Win32 Fonts. 327 // Reuse code to load Win32 Fonts.
330 DCHECK(!paint.getTypeface()); 328 SkASSERT(!paint.getTypeface());
331 return true; 329 return true;
332 } 330 }
333 331
334 void VectorDevice::setMatrixClip(const SkMatrix& transform, 332 void VectorDevice::setMatrixClip(const SkMatrix& transform,
335 const SkRegion& region) { 333 const SkRegion& region) {
336 transform_ = transform; 334 transform_ = transform;
337 LoadTransformToDC(hdc_, transform_); 335 LoadTransformToDC(hdc_, transform_);
338 clip_region_ = region; 336 clip_region_ = region;
339 if (!clip_region_.isEmpty()) 337 if (!clip_region_.isEmpty())
340 LoadClipRegion(); 338 LoadClipRegion();
341 } 339 }
342 340
343 void VectorDevice::drawToHDC(HDC dc, int x, int y, const RECT* src_rect) { 341 void VectorDevice::drawToHDC(HDC dc, int x, int y, const RECT* src_rect) {
344 NOTREACHED(); 342 SkASSERT(false);
345 } 343 }
346 344
347 void VectorDevice::LoadClipRegion() { 345 void VectorDevice::LoadClipRegion() {
348 SkMatrix t; 346 SkMatrix t;
349 t.reset(); 347 t.reset();
350 LoadClippingRegionToDC(hdc_, clip_region_, t); 348 LoadClippingRegionToDC(hdc_, clip_region_, t);
351 } 349 }
352 350
353 bool VectorDevice::CreateBrush(bool use_brush, COLORREF color) { 351 bool VectorDevice::CreateBrush(bool use_brush, COLORREF color) {
354 DCHECK(previous_brush_ == NULL); 352 SkASSERT(previous_brush_ == NULL);
355 // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer. 353 // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer.
356 // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use 354 // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use
357 // WHITE_BRUSH instead. 355 // WHITE_BRUSH instead.
358 356
359 if (!use_brush) { 357 if (!use_brush) {
360 // Set the transparency. 358 // Set the transparency.
361 if (0 == SetBkMode(hdc_, TRANSPARENT)) { 359 if (0 == SetBkMode(hdc_, TRANSPARENT)) {
362 NOTREACHED(); 360 SkASSERT(false);
363 return false; 361 return false;
364 } 362 }
365 363
366 // Select the NULL brush. 364 // Select the NULL brush.
367 previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH)); 365 previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH));
368 return previous_brush_ != NULL; 366 return previous_brush_ != NULL;
369 } 367 }
370 368
371 // Set the opacity. 369 // Set the opacity.
372 if (0 == SetBkMode(hdc_, OPAQUE)) { 370 if (0 == SetBkMode(hdc_, OPAQUE)) {
373 NOTREACHED(); 371 SkASSERT(false);
374 return false; 372 return false;
375 } 373 }
376 374
377 // Create and select the brush. 375 // Create and select the brush.
378 previous_brush_ = SelectObject(CreateSolidBrush(color)); 376 previous_brush_ = SelectObject(CreateSolidBrush(color));
379 return previous_brush_ != NULL; 377 return previous_brush_ != NULL;
380 } 378 }
381 379
382 bool VectorDevice::CreatePen(bool use_pen, COLORREF color, int stroke_width, 380 bool VectorDevice::CreatePen(bool use_pen, COLORREF color, int stroke_width,
383 float stroke_miter, DWORD pen_style) { 381 float stroke_miter, DWORD pen_style) {
384 DCHECK(previous_pen_ == NULL); 382 SkASSERT(previous_pen_ == NULL);
385 // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer. 383 // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer.
386 // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN 384 // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN
387 // instead. 385 // instead.
388 386
389 // No pen case 387 // No pen case
390 if (!use_pen) { 388 if (!use_pen) {
391 previous_pen_ = SelectObject(GetStockObject(NULL_PEN)); 389 previous_pen_ = SelectObject(GetStockObject(NULL_PEN));
392 return previous_pen_ != NULL; 390 return previous_pen_ != NULL;
393 } 391 }
394 392
395 // Use the stock pen if the stroke width is 0. 393 // Use the stock pen if the stroke width is 0.
396 if (stroke_width == 0) { 394 if (stroke_width == 0) {
397 // Create a pen with the right color. 395 // Create a pen with the right color.
398 previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color)); 396 previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color));
399 return previous_pen_ != NULL; 397 return previous_pen_ != NULL;
400 } 398 }
401 399
402 // Load a custom pen. 400 // Load a custom pen.
403 LOGBRUSH brush; 401 LOGBRUSH brush;
404 brush.lbStyle = BS_SOLID; 402 brush.lbStyle = BS_SOLID;
405 brush.lbColor = color; 403 brush.lbColor = color;
406 brush.lbHatch = 0; 404 brush.lbHatch = 0;
407 HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL); 405 HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL);
408 DCHECK(pen != NULL); 406 SkASSERT(pen != NULL);
409 previous_pen_ = SelectObject(pen); 407 previous_pen_ = SelectObject(pen);
410 if (previous_pen_ == NULL) 408 if (previous_pen_ == NULL)
411 return false; 409 return false;
412 410
413 if (!SetMiterLimit(hdc_, stroke_miter, NULL)) { 411 if (!SetMiterLimit(hdc_, stroke_miter, NULL)) {
414 NOTREACHED(); 412 SkASSERT(false);
415 return false; 413 return false;
416 } 414 }
417 return true; 415 return true;
418 } 416 }
419 417
420 void VectorDevice::Cleanup() { 418 void VectorDevice::Cleanup() {
421 if (previous_brush_) { 419 if (previous_brush_) {
422 HGDIOBJ result = SelectObject(previous_brush_); 420 HGDIOBJ result = SelectObject(previous_brush_);
423 previous_brush_ = NULL; 421 previous_brush_ = NULL;
424 if (result) { 422 if (result) {
425 BOOL res = DeleteObject(result); 423 BOOL res = DeleteObject(result);
426 DCHECK(res != 0); 424 SkASSERT(res != 0);
427 } 425 }
428 } 426 }
429 if (previous_pen_) { 427 if (previous_pen_) {
430 HGDIOBJ result = SelectObject(previous_pen_); 428 HGDIOBJ result = SelectObject(previous_pen_);
431 previous_pen_ = NULL; 429 previous_pen_ = NULL;
432 if (result) { 430 if (result) {
433 BOOL res = DeleteObject(result); 431 BOOL res = DeleteObject(result);
434 DCHECK(res != 0); 432 SkASSERT(res != 0);
435 } 433 }
436 } 434 }
437 // Remove any loaded path from the context. 435 // Remove any loaded path from the context.
438 AbortPath(hdc_); 436 AbortPath(hdc_);
439 } 437 }
440 438
441 HGDIOBJ VectorDevice::SelectObject(HGDIOBJ object) { 439 HGDIOBJ VectorDevice::SelectObject(HGDIOBJ object) {
442 HGDIOBJ result = ::SelectObject(hdc_, object); 440 HGDIOBJ result = ::SelectObject(hdc_, object);
443 DCHECK(result != HGDI_ERROR); 441 SkASSERT(result != HGDI_ERROR);
444 if (result == HGDI_ERROR) 442 if (result == HGDI_ERROR)
445 return NULL; 443 return NULL;
446 return result; 444 return result;
447 } 445 }
448 446
449 bool VectorDevice::CreateBrush(bool use_brush, const SkPaint& paint) { 447 bool VectorDevice::CreateBrush(bool use_brush, const SkPaint& paint) {
450 // Make sure that for transparent color, no brush is used. 448 // Make sure that for transparent color, no brush is used.
451 if (paint.getAlpha() == 0) { 449 if (paint.getAlpha() == 0) {
452 // Test if it ever happen. 450 // Test if it ever happen.
453 NOTREACHED(); 451 SkASSERT(false);
454 use_brush = false; 452 use_brush = false;
455 } 453 }
456 454
457 return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor())); 455 return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor()));
458 } 456 }
459 457
460 bool VectorDevice::CreatePen(bool use_pen, const SkPaint& paint) { 458 bool VectorDevice::CreatePen(bool use_pen, const SkPaint& paint) {
461 // Make sure that for transparent color, no pen is used. 459 // Make sure that for transparent color, no pen is used.
462 if (paint.getAlpha() == 0) { 460 if (paint.getAlpha() == 0) {
463 // Test if it ever happen. 461 // Test if it ever happen.
464 NOTREACHED(); 462 SkASSERT(false);
465 use_pen = false; 463 use_pen = false;
466 } 464 }
467 465
468 DWORD pen_style = PS_GEOMETRIC | PS_SOLID; 466 DWORD pen_style = PS_GEOMETRIC | PS_SOLID;
469 switch (paint.getStrokeJoin()) { 467 switch (paint.getStrokeJoin()) {
470 case SkPaint::kMiter_Join: 468 case SkPaint::kMiter_Join:
471 // Connects path segments with a sharp join. 469 // Connects path segments with a sharp join.
472 pen_style |= PS_JOIN_MITER; 470 pen_style |= PS_JOIN_MITER;
473 break; 471 break;
474 case SkPaint::kRound_Join: 472 case SkPaint::kRound_Join:
475 // Connects path segments with a round join. 473 // Connects path segments with a round join.
476 pen_style |= PS_JOIN_ROUND; 474 pen_style |= PS_JOIN_ROUND;
477 break; 475 break;
478 case SkPaint::kBevel_Join: 476 case SkPaint::kBevel_Join:
479 // Connects path segments with a flat bevel join. 477 // Connects path segments with a flat bevel join.
480 pen_style |= PS_JOIN_BEVEL; 478 pen_style |= PS_JOIN_BEVEL;
481 break; 479 break;
482 default: 480 default:
483 NOTREACHED(); 481 SkASSERT(false);
484 break; 482 break;
485 } 483 }
486 switch (paint.getStrokeCap()) { 484 switch (paint.getStrokeCap()) {
487 case SkPaint::kButt_Cap: 485 case SkPaint::kButt_Cap:
488 // Begin/end contours with no extension. 486 // Begin/end contours with no extension.
489 pen_style |= PS_ENDCAP_FLAT; 487 pen_style |= PS_ENDCAP_FLAT;
490 break; 488 break;
491 case SkPaint::kRound_Cap: 489 case SkPaint::kRound_Cap:
492 // Begin/end contours with a semi-circle extension. 490 // Begin/end contours with a semi-circle extension.
493 pen_style |= PS_ENDCAP_ROUND; 491 pen_style |= PS_ENDCAP_ROUND;
494 break; 492 break;
495 case SkPaint::kSquare_Cap: 493 case SkPaint::kSquare_Cap:
496 // Begin/end contours with a half square extension. 494 // Begin/end contours with a half square extension.
497 pen_style |= PS_ENDCAP_SQUARE; 495 pen_style |= PS_ENDCAP_SQUARE;
498 break; 496 break;
499 default: 497 default:
500 NOTREACHED(); 498 SkASSERT(false);
501 break; 499 break;
502 } 500 }
503 501
504 return CreatePen(use_pen, 502 return CreatePen(use_pen,
505 SkColorToCOLORREF(paint.getColor()), 503 SkColorToCOLORREF(paint.getColor()),
506 SkScalarRound(paint.getStrokeWidth()), 504 SkScalarRound(paint.getStrokeWidth()),
507 paint.getStrokeMiter(), 505 paint.getStrokeMiter(),
508 pen_style); 506 pen_style);
509 } 507 }
510 508
511 void VectorDevice::InternalDrawBitmap(const SkBitmap& bitmap, int x, int y, 509 void VectorDevice::InternalDrawBitmap(const SkBitmap& bitmap, int x, int y,
512 const SkPaint& paint) { 510 const SkPaint& paint) {
513 uint8 alpha = paint.getAlpha(); 511 unsigned char alpha = paint.getAlpha();
514 if (alpha == 0) 512 if (alpha == 0)
515 return; 513 return;
516 514
517 bool is_translucent; 515 bool is_translucent;
518 if (alpha != 255) { 516 if (alpha != 255) {
519 // ApplyPaint expect an opaque color. 517 // ApplyPaint expect an opaque color.
520 SkPaint tmp_paint(paint); 518 SkPaint tmp_paint(paint);
521 tmp_paint.setAlpha(255); 519 tmp_paint.setAlpha(255);
522 if (!ApplyPaint(tmp_paint)) 520 if (!ApplyPaint(tmp_paint))
523 return; 521 return;
524 is_translucent = true; 522 is_translucent = true;
525 } else { 523 } else {
526 if (!ApplyPaint(paint)) 524 if (!ApplyPaint(paint))
527 return; 525 return;
528 is_translucent = false; 526 is_translucent = false;
529 } 527 }
530 int src_size_x = bitmap.width(); 528 int src_size_x = bitmap.width();
531 int src_size_y = bitmap.height(); 529 int src_size_y = bitmap.height();
532 if (!src_size_x || !src_size_y) 530 if (!src_size_x || !src_size_y)
533 return; 531 return;
534 532
535 // Create a BMP v4 header that we can serialize. 533 // Create a BMP v4 header that we can serialize.
536 BITMAPV4HEADER bitmap_header; 534 BITMAPV4HEADER bitmap_header;
537 gfx::CreateBitmapV4Header(src_size_x, src_size_y, &bitmap_header); 535 gfx::CreateBitmapV4Header(src_size_x, src_size_y, &bitmap_header);
538 HDC dc = getBitmapDC(); 536 HDC dc = getBitmapDC();
539 SkAutoLockPixels lock(bitmap); 537 SkAutoLockPixels lock(bitmap);
540 DCHECK_EQ(bitmap.getConfig(), SkBitmap::kARGB_8888_Config); 538 SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
541 const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels()); 539 const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels());
542 if (pixels == NULL) { 540 if (pixels == NULL) {
543 NOTREACHED(); 541 SkASSERT(false);
544 return; 542 return;
545 } 543 }
546 544
547 if (!is_translucent) { 545 if (!is_translucent) {
548 int row_length = bitmap.rowBytesAsPixels(); 546 int row_length = bitmap.rowBytesAsPixels();
549 // There is no quick way to determine if an image is opaque. 547 // There is no quick way to determine if an image is opaque.
550 for (int y2 = 0; y2 < src_size_y; ++y2) { 548 for (int y2 = 0; y2 < src_size_y; ++y2) {
551 for (int x2 = 0; x2 < src_size_x; ++x2) { 549 for (int x2 = 0; x2 < src_size_x; ++x2) {
552 if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) { 550 if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) {
553 is_translucent = true; 551 is_translucent = true;
554 y2 = src_size_y; 552 y2 = src_size_y;
555 break; 553 break;
556 } 554 }
557 } 555 }
558 } 556 }
559 } 557 }
560 558
561 BITMAPINFOHEADER hdr; 559 BITMAPINFOHEADER hdr;
562 gfx::CreateBitmapHeader(src_size_x, src_size_y, &hdr); 560 gfx::CreateBitmapHeader(src_size_x, src_size_y, &hdr);
563 if (is_translucent) { 561 if (is_translucent) {
564 // The image must be loaded as a bitmap inside a device context. 562 // The image must be loaded as a bitmap inside a device context.
565 ScopedHDC bitmap_dc(::CreateCompatibleDC(dc)); 563 HDC bitmap_dc = ::CreateCompatibleDC(dc);
566 void* bits = NULL; 564 void* bits = NULL;
567 ScopedBitmap hbitmap(::CreateDIBSection( 565 HBITMAP hbitmap = ::CreateDIBSection(
568 bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr), 566 bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr),
569 DIB_RGB_COLORS, &bits, NULL, 0)); 567 DIB_RGB_COLORS, &bits, NULL, 0);
570 memcpy(bits, pixels, bitmap.getSize()); 568 memcpy(bits, pixels, bitmap.getSize());
571 DCHECK(hbitmap); 569 SkASSERT(hbitmap);
572 HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap); 570 HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap);
573 DeleteObject(old_bitmap);
574 571
575 // After some analysis of IE7's behavior, this is the thing to do. I was 572 // After some analysis of IE7's behavior, this is the thing to do. I was
576 // sure IE7 was doing so kind of bitmasking due to the way translucent image 573 // sure IE7 was doing so kind of bitmasking due to the way translucent image
577 // where renderered but after some windbg tracing, it is being done by the 574 // where renderered but after some windbg tracing, it is being done by the
578 // printer driver after all (mostly HP printers). IE7 always use AlphaBlend 575 // printer driver after all (mostly HP printers). IE7 always use AlphaBlend
579 // for bitmasked images. The trick seems to switch the stretching mode in 576 // for bitmasked images. The trick seems to switch the stretching mode in
580 // what the driver expects. 577 // what the driver expects.
581 DWORD previous_mode = GetStretchBltMode(dc); 578 DWORD previous_mode = GetStretchBltMode(dc);
582 BOOL result = SetStretchBltMode(dc, COLORONCOLOR); 579 BOOL result = SetStretchBltMode(dc, COLORONCOLOR);
583 DCHECK(result); 580 SkASSERT(result);
584 // Note that this function expect premultiplied colors (!) 581 // Note that this function expect premultiplied colors (!)
585 BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; 582 BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
586 result = GdiAlphaBlend(dc, 583 result = GdiAlphaBlend(dc,
587 x, y, // Destination origin. 584 x, y, // Destination origin.
588 src_size_x, src_size_y, // Destination size. 585 src_size_x, src_size_y, // Destination size.
589 bitmap_dc, 586 bitmap_dc,
590 0, 0, // Source origin. 587 0, 0, // Source origin.
591 src_size_x, src_size_y, // Source size. 588 src_size_x, src_size_y, // Source size.
592 blend_function); 589 blend_function);
593 DCHECK(result); 590 SkASSERT(result);
594 result = SetStretchBltMode(dc, previous_mode); 591 result = SetStretchBltMode(dc, previous_mode);
595 DCHECK(result); 592 SkASSERT(result);
593
594 ::SelectObject(bitmap_dc, static_cast<HBITMAP>(old_bitmap));
595 DeleteObject(hbitmap);
596 DeleteDC(bitmap_dc);
596 } else { 597 } else {
597 BOOL result = StretchDIBits(dc, 598 BOOL result = StretchDIBits(dc,
598 x, y, // Destination origin. 599 x, y, // Destination origin.
599 src_size_x, src_size_y, 600 src_size_x, src_size_y,
600 0, 0, // Source origin. 601 0, 0, // Source origin.
601 src_size_x, src_size_y, // Source size. 602 src_size_x, src_size_y, // Source size.
602 pixels, 603 pixels,
603 reinterpret_cast<const BITMAPINFO*>(&hdr), 604 reinterpret_cast<const BITMAPINFO*>(&hdr),
604 DIB_RGB_COLORS, 605 DIB_RGB_COLORS,
605 SRCCOPY); 606 SRCCOPY);
606 DCHECK(result); 607 SkASSERT(result);
607 } 608 }
608 Cleanup(); 609 Cleanup();
609 } 610 }
610 611
611 } // namespace skia 612 } // namespace skia
612 613
OLDNEW
« no previous file with comments | « skia/ext/vector_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698