| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_mac.h" | 5 #include "skia/ext/bitmap_platform_device_mac.h" |
| 6 | 6 |
| 7 #include <time.h> | 7 #include <time.h> |
| 8 | 8 |
| 9 #include "base/mac_util.h" | 9 #include "base/mac_util.h" |
| 10 #include "base/ref_counted.h" | 10 #include "base/ref_counted.h" |
| 11 #include "skia/ext/bitmap_platform_device_data.h" |
| 11 #include "skia/ext/skia_utils_mac.h" | 12 #include "skia/ext/skia_utils_mac.h" |
| 12 #include "third_party/skia/include/core/SkMatrix.h" | 13 #include "third_party/skia/include/core/SkMatrix.h" |
| 13 #include "third_party/skia/include/core/SkRegion.h" | 14 #include "third_party/skia/include/core/SkRegion.h" |
| 14 #include "third_party/skia/include/core/SkTypes.h" | 15 #include "third_party/skia/include/core/SkTypes.h" |
| 15 #include "third_party/skia/include/core/SkUtils.h" | 16 #include "third_party/skia/include/core/SkUtils.h" |
| 16 | 17 |
| 17 namespace skia { | 18 namespace skia { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 69 |
| 69 // Change the coordinate system to match WebCore's | 70 // Change the coordinate system to match WebCore's |
| 70 CGContextTranslateCTM(context, 0, height); | 71 CGContextTranslateCTM(context, 0, height); |
| 71 CGContextScaleCTM(context, 1.0, -1.0); | 72 CGContextScaleCTM(context, 1.0, -1.0); |
| 72 | 73 |
| 73 return context; | 74 return context; |
| 74 } | 75 } |
| 75 | 76 |
| 76 } // namespace | 77 } // namespace |
| 77 | 78 |
| 78 class BitmapPlatformDevice::BitmapPlatformDeviceData : public SkRefCnt { | |
| 79 public: | |
| 80 explicit BitmapPlatformDeviceData(CGContextRef bitmap); | |
| 81 | |
| 82 // Create/destroy CoreGraphics context for our bitmap data. | |
| 83 CGContextRef GetBitmapContext() { | |
| 84 LoadConfig(); | |
| 85 return bitmap_context_; | |
| 86 } | |
| 87 | |
| 88 void ReleaseBitmapContext() { | |
| 89 SkASSERT(bitmap_context_); | |
| 90 CGContextRelease(bitmap_context_); | |
| 91 bitmap_context_ = NULL; | |
| 92 } | |
| 93 | |
| 94 // Sets the transform and clip operations. This will not update the CGContext, | |
| 95 // but will mark the config as dirty. The next call of LoadConfig will | |
| 96 // pick up these changes. | |
| 97 void SetMatrixClip(const SkMatrix& transform, const SkRegion& region); | |
| 98 | |
| 99 // Loads the current transform and clip into the DC. Can be called even when | |
| 100 // |bitmap_context_| is NULL (will be a NOP). | |
| 101 void LoadConfig(); | |
| 102 | |
| 103 // Lazily-created graphics context used to draw into the bitmap. | |
| 104 CGContextRef bitmap_context_; | |
| 105 | |
| 106 // True when there is a transform or clip that has not been set to the | |
| 107 // CGContext. The CGContext is retrieved for every text operation, and the | |
| 108 // transform and clip do not change as much. We can save time by not loading | |
| 109 // the clip and transform for every one. | |
| 110 bool config_dirty_; | |
| 111 | |
| 112 // Translation assigned to the CGContext: we need to keep track of this | |
| 113 // separately so it can be updated even if the CGContext isn't created yet. | |
| 114 SkMatrix transform_; | |
| 115 | |
| 116 // The current clipping | |
| 117 SkRegion clip_region_; | |
| 118 | |
| 119 private: | |
| 120 friend class base::RefCounted<BitmapPlatformDeviceData>; | |
| 121 ~BitmapPlatformDeviceData() { | |
| 122 if (bitmap_context_) | |
| 123 CGContextRelease(bitmap_context_); | |
| 124 } | |
| 125 | |
| 126 // Disallow copy & assign. | |
| 127 BitmapPlatformDeviceData(const BitmapPlatformDeviceData&); | |
| 128 BitmapPlatformDeviceData& operator=(const BitmapPlatformDeviceData&); | |
| 129 }; | |
| 130 | |
| 131 BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData( | 79 BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData( |
| 132 CGContextRef bitmap) | 80 CGContextRef bitmap) |
| 133 : bitmap_context_(bitmap), | 81 : bitmap_context_(bitmap), |
| 134 config_dirty_(true) { // Want to load the config next time. | 82 config_dirty_(true) { // Want to load the config next time. |
| 135 SkASSERT(bitmap_context_); | 83 SkASSERT(bitmap_context_); |
| 136 // Initialize the clip region to the entire bitmap. | 84 // Initialize the clip region to the entire bitmap. |
| 137 | 85 |
| 138 SkIRect rect; | 86 SkIRect rect; |
| 139 rect.set(0, 0, | 87 rect.set(0, 0, |
| 140 CGBitmapContextGetWidth(bitmap_context_), | 88 CGBitmapContextGetWidth(bitmap_context_), |
| 141 CGBitmapContextGetHeight(bitmap_context_)); | 89 CGBitmapContextGetHeight(bitmap_context_)); |
| 142 clip_region_ = SkRegion(rect); | 90 clip_region_ = SkRegion(rect); |
| 143 transform_.reset(); | 91 transform_.reset(); |
| 144 CGContextRetain(bitmap_context_); | 92 CGContextRetain(bitmap_context_); |
| 145 // We must save the state once so that we can use the restore/save trick | 93 // We must save the state once so that we can use the restore/save trick |
| 146 // in LoadConfig(). | 94 // in LoadConfig(). |
| 147 CGContextSaveGState(bitmap_context_); | 95 CGContextSaveGState(bitmap_context_); |
| 148 } | 96 } |
| 149 | 97 |
| 98 BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() { |
| 99 if (bitmap_context_) |
| 100 CGContextRelease(bitmap_context_); |
| 101 } |
| 102 |
| 150 void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip( | 103 void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip( |
| 151 const SkMatrix& transform, | 104 const SkMatrix& transform, |
| 152 const SkRegion& region) { | 105 const SkRegion& region) { |
| 153 transform_ = transform; | 106 transform_ = transform; |
| 154 clip_region_ = region; | 107 clip_region_ = region; |
| 155 config_dirty_ = true; | 108 config_dirty_ = true; |
| 156 } | 109 } |
| 157 | 110 |
| 158 void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() { | 111 void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() { |
| 159 if (!config_dirty_ || !bitmap_context_) | 112 if (!config_dirty_ || !bitmap_context_) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 } | 220 } |
| 268 | 221 |
| 269 BitmapPlatformDevice& BitmapPlatformDevice::operator=( | 222 BitmapPlatformDevice& BitmapPlatformDevice::operator=( |
| 270 const BitmapPlatformDevice& other) { | 223 const BitmapPlatformDevice& other) { |
| 271 data_ = other.data_; | 224 data_ = other.data_; |
| 272 data_->ref(); | 225 data_->ref(); |
| 273 return *this; | 226 return *this; |
| 274 } | 227 } |
| 275 | 228 |
| 276 CGContextRef BitmapPlatformDevice::GetBitmapContext() { | 229 CGContextRef BitmapPlatformDevice::GetBitmapContext() { |
| 277 return data_->GetBitmapContext(); | 230 data_->LoadConfig(); |
| 231 return data_->bitmap_context(); |
| 278 } | 232 } |
| 279 | 233 |
| 280 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform, | 234 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform, |
| 281 const SkRegion& region) { | 235 const SkRegion& region) { |
| 282 data_->SetMatrixClip(transform, region); | 236 data_->SetMatrixClip(transform, region); |
| 283 } | 237 } |
| 284 | 238 |
| 285 void BitmapPlatformDevice::DrawToContext(CGContextRef context, int x, int y, | 239 void BitmapPlatformDevice::DrawToContext(CGContextRef context, int x, int y, |
| 286 const CGRect* src_rect) { | 240 const CGRect* src_rect) { |
| 287 bool created_dc = false; | 241 bool created_dc = false; |
| 288 if (!data_->bitmap_context_) { | 242 if (!data_->bitmap_context()) { |
| 289 created_dc = true; | 243 created_dc = true; |
| 290 GetBitmapContext(); | 244 GetBitmapContext(); |
| 291 } | 245 } |
| 292 | 246 |
| 293 // this should not make a copy of the bits, since we're not doing | 247 // this should not make a copy of the bits, since we're not doing |
| 294 // anything to trigger copy on write | 248 // anything to trigger copy on write |
| 295 CGImageRef image = CGBitmapContextCreateImage(data_->bitmap_context_); | 249 CGImageRef image = CGBitmapContextCreateImage(data_->bitmap_context()); |
| 296 CGRect bounds; | 250 CGRect bounds; |
| 297 bounds.origin.x = x; | 251 bounds.origin.x = x; |
| 298 bounds.origin.y = y; | 252 bounds.origin.y = y; |
| 299 if (src_rect) { | 253 if (src_rect) { |
| 300 bounds.size.width = src_rect->size.width; | 254 bounds.size.width = src_rect->size.width; |
| 301 bounds.size.height = src_rect->size.height; | 255 bounds.size.height = src_rect->size.height; |
| 302 CGImageRef sub_image = CGImageCreateWithImageInRect(image, *src_rect); | 256 CGImageRef sub_image = CGImageCreateWithImageInRect(image, *src_rect); |
| 303 CGContextDrawImage(context, bounds, sub_image); | 257 CGContextDrawImage(context, bounds, sub_image); |
| 304 CGImageRelease(sub_image); | 258 CGImageRelease(sub_image); |
| 305 } else { | 259 } else { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 322 } | 276 } |
| 323 | 277 |
| 324 void BitmapPlatformDevice::onAccessBitmap(SkBitmap*) { | 278 void BitmapPlatformDevice::onAccessBitmap(SkBitmap*) { |
| 325 // Not needed in CoreGraphics | 279 // Not needed in CoreGraphics |
| 326 } | 280 } |
| 327 | 281 |
| 328 void BitmapPlatformDevice::processPixels(int x, int y, | 282 void BitmapPlatformDevice::processPixels(int x, int y, |
| 329 int width, int height, | 283 int width, int height, |
| 330 adjustAlpha adjustor) { | 284 adjustAlpha adjustor) { |
| 331 const SkBitmap& bitmap = accessBitmap(true); | 285 const SkBitmap& bitmap = accessBitmap(true); |
| 332 SkMatrix& matrix = data_->transform_; | 286 const SkMatrix& matrix = data_->transform(); |
| 333 int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x; | 287 int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x; |
| 334 int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y; | 288 int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y; |
| 335 | 289 |
| 336 SkAutoLockPixels lock(bitmap); | 290 SkAutoLockPixels lock(bitmap); |
| 337 if (Constrain(bitmap.width(), &bitmap_start_x, &width) && | 291 if (Constrain(bitmap.width(), &bitmap_start_x, &width) && |
| 338 Constrain(bitmap.height(), &bitmap_start_y, &height)) { | 292 Constrain(bitmap.height(), &bitmap_start_y, &height)) { |
| 339 uint32_t* data = bitmap.getAddr32(0, 0); | 293 uint32_t* data = bitmap.getAddr32(0, 0); |
| 340 size_t row_words = bitmap.rowBytes() / 4; | 294 size_t row_words = bitmap.rowBytes() / 4; |
| 341 for (int i = 0; i < height; i++) { | 295 for (int i = 0; i < height; i++) { |
| 342 size_t offset = (i + bitmap_start_y) * row_words + bitmap_start_x; | 296 size_t offset = (i + bitmap_start_y) * row_words + bitmap_start_x; |
| 343 for (int j = 0; j < width; j++) { | 297 for (int j = 0; j < width; j++) { |
| 344 adjustor(data + offset + j); | 298 adjustor(data + offset + j); |
| 345 } | 299 } |
| 346 } | 300 } |
| 347 } | 301 } |
| 348 } | 302 } |
| 349 | 303 |
| 350 } // namespace skia | 304 } // namespace skia |
| OLD | NEW |