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

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

Issue 21201: Transparency (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « skia/ext/bitmap_platform_device_win.h ('k') | skia/ext/platform_canvas_unittest.cc » ('j') | 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/bitmap_platform_device_win.h" 5 #include "skia/ext/bitmap_platform_device_win.h"
6 6
7 #include "SkMatrix.h" 7 #include "SkMatrix.h"
8 #include "SkRefCnt.h" 8 #include "SkRefCnt.h"
9 #include "SkRegion.h" 9 #include "SkRegion.h"
10 #include "SkUtils.h" 10 #include "SkUtils.h"
11 11
12 namespace skia { 12 namespace skia {
13 13
14 // When Windows draws text, is sets the fourth byte (which Skia uses for alpha)
15 // to zero. This means that if we try compositing with text that Windows has
16 // drawn, we get invalid color values (if the alpha is 0, the other channels
17 // should be 0 since Skia uses premultiplied colors) and strange results.
18 //
19 // HTML rendering only requires one bit of transparency. When you ask for a
20 // semitransparent div, the div itself is drawn in another layer as completely
21 // opaque, and then composited onto the lower layer with a transfer function.
22 // The only place an alpha channel is needed is to track what has been drawn
23 // and what has not been drawn.
24 //
25 // Therefore, when we allocate a new device, we fill it with this special
26 // color. Because Skia uses premultiplied colors, any color where the alpha
27 // channel is smaller than any component is impossible, so we know that no
28 // legitimate drawing will produce this color. We use 1 as the alpha value
29 // because 0 is produced when Windows draws text (even though it should be
30 // opaque).
31 //
32 // When a layer is done and we want to render it to a lower layer, we use
33 // fixupAlphaBeforeCompositing. This replaces all 0 alpha channels with
34 // opaque (to fix the text problem), and replaces this magic color value
35 // with transparency. The result is something that can be correctly
36 // composited. However, once this has been done, no more can be drawn to
37 // the layer because fixing the alphas *again* will result in incorrect
38 // values.
39 static const uint32_t kMagicTransparencyColor = 0x01FFFEFD;
40
41 namespace { 14 namespace {
42 15
43 // Constrains position and size to fit within available_size. If |size| is -1, 16 // Constrains position and size to fit within available_size. If |size| is -1,
44 // all the available_size is used. Returns false if the position is out of 17 // all the available_size is used. Returns false if the position is out of
45 // available_size. 18 // available_size.
46 bool Constrain(int available_size, int* position, int *size) { 19 bool Constrain(int available_size, int* position, int *size) {
47 if (*size < -2) 20 if (*size < -2)
48 return false; 21 return false;
49 22
50 if (*position < 0) { 23 if (*position < 0) {
51 if (*size != -1) 24 if (*size != -1)
52 *size += *position; 25 *size += *position;
53 *position = 0; 26 *position = 0;
54 } 27 }
55 if (*size == 0 || *position >= available_size) 28 if (*size == 0 || *position >= available_size)
56 return false; 29 return false;
57 30
58 if (*size > 0) { 31 if (*size > 0) {
59 int overflow = (*position + *size) - available_size; 32 int overflow = (*position + *size) - available_size;
60 if (overflow > 0) { 33 if (overflow > 0) {
61 *size -= overflow; 34 *size -= overflow;
62 } 35 }
63 } else { 36 } else {
64 // Fill up available size. 37 // Fill up available size.
65 *size = available_size - *position; 38 *size = available_size - *position;
66 } 39 }
67 return true; 40 return true;
68 } 41 }
69 42
70 // If the pixel value is 0, it gets set to kMagicTransparencyColor.
71 void PrepareAlphaForGDI(uint32_t* pixel) {
72 if (*pixel == 0) {
73 *pixel = kMagicTransparencyColor;
74 }
75 }
76
77 // If the pixel value is kMagicTransparencyColor, it gets set to 0. Otherwise
78 // if the alpha is 0, the alpha is set to 255.
79 void PostProcessAlphaForGDI(uint32_t* pixel) {
80 if (*pixel == kMagicTransparencyColor) {
81 *pixel = 0;
82 } else if ((*pixel & 0xFF000000) == 0) {
83 *pixel |= 0xFF000000;
84 }
85 }
86
87 // Sets the opacity of the specified value to 0xFF.
88 void MakeOpaqueAlphaAdjuster(uint32_t* pixel) {
89 *pixel |= 0xFF000000;
90 }
91
92 // See the declaration of kMagicTransparencyColor at the top of the file.
93 void FixupAlphaBeforeCompositing(uint32_t* pixel) {
94 if (*pixel == kMagicTransparencyColor)
95 *pixel = 0;
96 else
97 *pixel |= 0xFF000000;
98 }
99
100 } // namespace 43 } // namespace
101 44
102 class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData : public SkRefCnt { 45 class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData : public SkRefCnt {
103 public: 46 public:
104 explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap); 47 explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap);
105 48
106 // Create/destroy hdc_, which is the memory DC for our bitmap data. 49 // Create/destroy hdc_, which is the memory DC for our bitmap data.
107 HDC GetBitmapDC(); 50 HDC GetBitmapDC();
108 void ReleaseBitmapDC(); 51 void ReleaseBitmapDC();
109 bool IsBitmapDCCreated() const; 52 bool IsBitmapDCCreated() const;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 bitmap.setPixels(data); 216 bitmap.setPixels(data);
274 bitmap.setIsOpaque(is_opaque); 217 bitmap.setIsOpaque(is_opaque);
275 218
276 if (is_opaque) { 219 if (is_opaque) {
277 #ifndef NDEBUG 220 #ifndef NDEBUG
278 // To aid in finding bugs, we set the background color to something 221 // To aid in finding bugs, we set the background color to something
279 // obviously wrong so it will be noticable when it is not cleared 222 // obviously wrong so it will be noticable when it is not cleared
280 bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green 223 bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green
281 #endif 224 #endif
282 } else { 225 } else {
283 // A transparent layer is requested: fill with our magic "transparent" 226 bitmap.eraseARGB(0, 0, 0, 0);
284 // color, see the declaration of kMagicTransparencyColor above
285 sk_memset32(static_cast<uint32_t*>(data), kMagicTransparencyColor,
286 width * height);
287 } 227 }
288 228
289 // The device object will take ownership of the HBITMAP. The initial refcount 229 // The device object will take ownership of the HBITMAP. The initial refcount
290 // of the data object will be 1, which is what the constructor expects. 230 // of the data object will be 1, which is what the constructor expects.
291 return new BitmapPlatformDeviceWin(new BitmapPlatformDeviceWinData(hbitmap), 231 return new BitmapPlatformDeviceWin(new BitmapPlatformDeviceWinData(hbitmap),
292 bitmap); 232 bitmap);
293 } 233 }
294 234
295 // The device will own the HBITMAP, which corresponds to also owning the pixel 235 // The device will own the HBITMAP, which corresponds to also owning the pixel
296 // data. Therefore, we do not transfer ownership to the SkDevice's bitmap. 236 // data. Therefore, we do not transfer ownership to the SkDevice's bitmap.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 copy_width, 320 copy_width,
381 copy_height, 321 copy_height,
382 blend_function); 322 blend_function);
383 } 323 }
384 LoadTransformToDC(source_dc, data_->transform()); 324 LoadTransformToDC(source_dc, data_->transform());
385 325
386 if (created_dc) 326 if (created_dc)
387 data_->ReleaseBitmapDC(); 327 data_->ReleaseBitmapDC();
388 } 328 }
389 329
390 void BitmapPlatformDeviceWin::prepareForGDI(int x, int y, int width,
391 int height) {
392 processPixels<PrepareAlphaForGDI>(x, y, width, height);
393 }
394
395 void BitmapPlatformDeviceWin::postProcessGDI(int x, int y, int width,
396 int height) {
397 processPixels<PostProcessAlphaForGDI>(x, y, width, height);
398 }
399
400 void BitmapPlatformDeviceWin::makeOpaque(int x, int y, int width, int height) { 330 void BitmapPlatformDeviceWin::makeOpaque(int x, int y, int width, int height) {
401 processPixels<MakeOpaqueAlphaAdjuster>(x, y, width, height);
402 }
403
404 void BitmapPlatformDeviceWin::fixupAlphaBeforeCompositing() {
405 const SkBitmap& bitmap = accessBitmap(true);
406 SkAutoLockPixels lock(bitmap);
407 uint32_t* data = bitmap.getAddr32(0, 0);
408
409 size_t words = bitmap.rowBytes() / sizeof(uint32_t) * bitmap.height();
410 for (size_t i = 0; i < words; i++) {
411 if (data[i] == kMagicTransparencyColor)
412 data[i] = 0;
413 else
414 data[i] |= 0xFF000000;
415 }
416 }
417
418 // Returns the color value at the specified location.
419 SkColor BitmapPlatformDeviceWin::getColorAt(int x, int y) {
420 const SkBitmap& bitmap = accessBitmap(false);
421 SkAutoLockPixels lock(bitmap);
422 uint32_t* data = bitmap.getAddr32(0, 0);
423 return static_cast<SkColor>(data[x + y * width()]);
424 }
425
426 void BitmapPlatformDeviceWin::onAccessBitmap(SkBitmap* bitmap) {
427 // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
428 // operation has occurred on our DC.
429 if (data_->IsBitmapDCCreated())
430 GdiFlush();
431 }
432
433 template<BitmapPlatformDeviceWin::adjustAlpha adjustor>
434 void BitmapPlatformDeviceWin::processPixels(int x,
435 int y,
436 int width,
437 int height) {
438 const SkBitmap& bitmap = accessBitmap(true); 331 const SkBitmap& bitmap = accessBitmap(true);
439 SkASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); 332 SkASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
333
334 // FIXME(brettw): This is kind of lame, we shouldn't be dealing with
335 // transforms at this level. Probably there should be a PlatformCanvas
336 // function that does the transform (using the actual transform not just the
337 // translation) and calls us with the transformed rect.
440 const SkMatrix& matrix = data_->transform(); 338 const SkMatrix& matrix = data_->transform();
441 int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x; 339 int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x;
442 int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y; 340 int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y;
443 341
444 if (Constrain(bitmap.width(), &bitmap_start_x, &width) && 342 if (Constrain(bitmap.width(), &bitmap_start_x, &width) &&
445 Constrain(bitmap.height(), &bitmap_start_y, &height)) { 343 Constrain(bitmap.height(), &bitmap_start_y, &height)) {
446 SkAutoLockPixels lock(bitmap); 344 SkAutoLockPixels lock(bitmap);
447 SkASSERT(bitmap.rowBytes() % sizeof(uint32_t) == 0u); 345 SkASSERT(bitmap.rowBytes() % sizeof(uint32_t) == 0u);
448 size_t row_words = bitmap.rowBytes() / sizeof(uint32_t); 346 size_t row_words = bitmap.rowBytes() / sizeof(uint32_t);
449 // Set data to the first pixel to be modified. 347 // Set data to the first pixel to be modified.
450 uint32_t* data = bitmap.getAddr32(0, 0) + (bitmap_start_y * row_words) + 348 uint32_t* data = bitmap.getAddr32(0, 0) + (bitmap_start_y * row_words) +
451 bitmap_start_x; 349 bitmap_start_x;
452 for (int i = 0; i < height; i++) { 350 for (int i = 0; i < height; i++) {
453 for (int j = 0; j < width; j++) { 351 for (int j = 0; j < width; j++)
454 adjustor(data + j); 352 data[j] |= (0xFF << SK_A32_SHIFT);
455 }
456 data += row_words; 353 data += row_words;
457 } 354 }
458 } 355 }
459 } 356 }
460 357
358 // Returns the color value at the specified location.
359 SkColor BitmapPlatformDeviceWin::getColorAt(int x, int y) {
360 const SkBitmap& bitmap = accessBitmap(false);
361 SkAutoLockPixels lock(bitmap);
362 uint32_t* data = bitmap.getAddr32(0, 0);
363 return static_cast<SkColor>(data[x + y * width()]);
364 }
365
366 void BitmapPlatformDeviceWin::onAccessBitmap(SkBitmap* bitmap) {
367 // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI
368 // operation has occurred on our DC.
369 if (data_->IsBitmapDCCreated())
370 GdiFlush();
371 }
372
461 } // namespace skia 373 } // namespace skia
462 374
OLDNEW
« no previous file with comments | « skia/ext/bitmap_platform_device_win.h ('k') | skia/ext/platform_canvas_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698