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

Side by Side Diff: skia/ext/skia_utils_mac.mm

Issue 2001653002: Remove SkDevice, obsolete constructor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: expect inverse CTM to avoid additional clipping Created 4 years, 6 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
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 "skia/ext/skia_utils_mac.h" 5 #include "skia/ext/skia_utils_mac.h"
6 6
7 #import <AppKit/AppKit.h> 7 #import <AppKit/AppKit.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <memory> 10 #include <memory>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/mac/scoped_cftyperef.h" 13 #include "base/mac/scoped_cftyperef.h"
14 #include "base/mac/scoped_nsobject.h" 14 #include "base/mac/scoped_nsobject.h"
15 #include "skia/ext/bitmap_platform_device_mac.h"
16 #include "skia/ext/platform_canvas.h" 15 #include "skia/ext/platform_canvas.h"
17 #include "third_party/skia/include/utils/mac/SkCGUtils.h" 16 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
18 17
19 namespace { 18 namespace {
20 19
21 // Draws an NSImage or an NSImageRep with a given size into a SkBitmap. 20 // Draws an NSImage or an NSImageRep with a given size into a SkBitmap.
22 SkBitmap NSImageOrNSImageRepToSkBitmapWithColorSpace( 21 SkBitmap NSImageOrNSImageRepToSkBitmapWithColorSpace(
23 NSImage* image, 22 NSImage* image,
24 NSImageRep* image_rep, 23 NSImageRep* image_rep,
25 NSSize size, 24 NSSize size,
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 count:4]; 183 count:4];
185 } 184 }
186 185
187 SkBitmap CGImageToSkBitmap(CGImageRef image) { 186 SkBitmap CGImageToSkBitmap(CGImageRef image) {
188 if (!image) 187 if (!image)
189 return SkBitmap(); 188 return SkBitmap();
190 189
191 int width = CGImageGetWidth(image); 190 int width = CGImageGetWidth(image);
192 int height = CGImageGetHeight(image); 191 int height = CGImageGetHeight(image);
193 192
194 sk_sp<skia::BitmapPlatformDevice> device( 193 sk_sp<SkCanvas> canvas(skia::CreatePlatformCanvas(
195 skia::BitmapPlatformDevice::Create(NULL, width, height, false)); 194 nullptr, width, height, false, RETURN_NULL_ON_FAILURE));
196
197 sk_sp<SkCanvas> canvas(skia::CreateCanvas(device, RETURN_NULL_ON_FAILURE));
198 ScopedPlatformPaint p(canvas.get()); 195 ScopedPlatformPaint p(canvas.get());
199 CGContextRef context = p.GetPlatformSurface(); 196 CGContextRef context = p.GetPlatformSurface();
200 197
201 // We need to invert the y-axis of the canvas so that Core Graphics drawing 198 // We need to invert the y-axis of the canvas so that Core Graphics drawing
202 // happens right-side up. Skia has an upper-left origin and CG has a lower- 199 // happens right-side up. Skia has an upper-left origin and CG has a lower-
203 // left one. 200 // left one.
204 CGContextScaleCTM(context, 1.0, -1.0); 201 CGContextScaleCTM(context, 1.0, -1.0);
205 CGContextTranslateCTM(context, 0, -height); 202 CGContextTranslateCTM(context, 0, -height);
206 203
207 // We want to copy transparent pixels from |image|, instead of blending it 204 // We want to copy transparent pixels from |image|, instead of blending it
208 // onto uninitialized pixels. 205 // onto uninitialized pixels.
209 CGContextSetBlendMode(context, kCGBlendModeCopy); 206 CGContextSetBlendMode(context, kCGBlendModeCopy);
210 207
211 CGRect rect = CGRectMake(0, 0, width, height); 208 CGRect rect = CGRectMake(0, 0, width, height);
212 CGContextDrawImage(context, rect, image); 209 CGContextDrawImage(context, rect, image);
213 210
214 // Because |device| will be cleaned up and will take its pixels with it, we 211 return skia::ReadPixels(canvas.get());
215 // copy it to the stack and return it.
216 SkBitmap bitmap = device->accessBitmap(false);
217
218 return bitmap;
219 } 212 }
220 213
221 SkBitmap NSImageToSkBitmapWithColorSpace( 214 SkBitmap NSImageToSkBitmapWithColorSpace(
222 NSImage* image, bool is_opaque, CGColorSpaceRef color_space) { 215 NSImage* image, bool is_opaque, CGColorSpaceRef color_space) {
223 return NSImageOrNSImageRepToSkBitmapWithColorSpace( 216 return NSImageOrNSImageRepToSkBitmapWithColorSpace(
224 image, nil, [image size], is_opaque, color_space); 217 image, nil, [image size], is_opaque, color_space);
225 } 218 }
226 219
227 SkBitmap NSImageRepToSkBitmapWithColorSpace(NSImageRep* image_rep, 220 SkBitmap NSImageRepToSkBitmapWithColorSpace(NSImageRep* image_rep,
228 NSSize size, 221 NSSize size,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 [image setSize:NSMakeSize(skiaBitmap.width(), skiaBitmap.height())]; 255 [image setSize:NSMakeSize(skiaBitmap.width(), skiaBitmap.height())];
263 return [image.release() autorelease]; 256 return [image.release() autorelease];
264 } 257 }
265 258
266 NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) { 259 NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) {
267 base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace( 260 base::ScopedCFTypeRef<CGColorSpaceRef> colorSpace(
268 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); 261 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
269 return SkBitmapToNSImageWithColorSpace(skiaBitmap, colorSpace.get()); 262 return SkBitmapToNSImageWithColorSpace(skiaBitmap, colorSpace.get());
270 } 263 }
271 264
272 SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas)
273 : canvas_(canvas),
274 userClipRectSpecified_(false),
275 cgContext_(0),
276 bitmapScaleFactor_(1),
277 useDeviceBits_(false),
278 bitmapIsDummy_(false) {
279 }
280
281 SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas, 265 SkiaBitLocker::SkiaBitLocker(SkCanvas* canvas,
282 const SkIRect& userClipRect, 266 const SkIRect& userClipRect,
283 SkScalar bitmapScaleFactor) 267 SkScalar bitmapScaleFactor)
284 : canvas_(canvas), 268 : canvas_(canvas),
285 userClipRectSpecified_(true),
286 cgContext_(0), 269 cgContext_(0),
287 bitmapScaleFactor_(bitmapScaleFactor), 270 bitmapScaleFactor_(bitmapScaleFactor),
288 useDeviceBits_(false), 271 useDeviceBits_(false),
289 bitmapIsDummy_(false) { 272 bitmapIsDummy_(false) {
290 canvas_->save(); 273 canvas_->save();
291 canvas_->clipRect(SkRect::MakeFromIRect(userClipRect)); 274 canvas_->clipRect(SkRect::MakeFromIRect(userClipRect));
292 } 275 }
293 276
294 SkiaBitLocker::~SkiaBitLocker() { 277 SkiaBitLocker::~SkiaBitLocker() {
295 releaseIfNeeded(); 278 releaseIfNeeded();
296 if (userClipRectSpecified_) 279 canvas_->restore();
297 canvas_->restore();
298 } 280 }
299 281
300 SkIRect SkiaBitLocker::computeDirtyRect() { 282 SkIRect SkiaBitLocker::computeDirtyRect() {
301 // If the user specified a clip region, assume that it was tight and that the 283 // If the user specified a clip region, assume that it was tight and that the
302 // dirty rect is approximately the whole bitmap. 284 // dirty rect is approximately the whole bitmap.
303 if (userClipRectSpecified_) 285 return SkIRect::MakeWH(offscreen_.width(), offscreen_.height());
304 return SkIRect::MakeWH(offscreen_.width(), offscreen_.height());
305
306 // Find the bits that were drawn to.
307 SkAutoLockPixels lockedPixels(offscreen_);
308 const uint32_t* pixelBase
309 = reinterpret_cast<uint32_t*>(offscreen_.getPixels());
310 int rowPixels = offscreen_.rowBytesAsPixels();
311 int width = offscreen_.width();
312 int height = offscreen_.height();
313 SkIRect bounds;
314 bounds.fTop = 0;
315 int x;
316 int y = -1;
317 const uint32_t* pixels = pixelBase;
318 while (++y < height) {
319 for (x = 0; x < width; ++x) {
320 if (pixels[x]) {
321 bounds.fTop = y;
322 goto foundTop;
323 }
324 }
325 pixels += rowPixels;
326 }
327 foundTop:
328 bounds.fBottom = height;
329 y = height;
330 pixels = pixelBase + rowPixels * (y - 1);
331 while (--y > bounds.fTop) {
332 for (x = 0; x < width; ++x) {
333 if (pixels[x]) {
334 bounds.fBottom = y + 1;
335 goto foundBottom;
336 }
337 }
338 pixels -= rowPixels;
339 }
340 foundBottom:
341 bounds.fLeft = 0;
342 x = -1;
343 while (++x < width) {
344 pixels = pixelBase + rowPixels * bounds.fTop;
345 for (y = bounds.fTop; y < bounds.fBottom; ++y) {
346 if (pixels[x]) {
347 bounds.fLeft = x;
348 goto foundLeft;
349 }
350 pixels += rowPixels;
351 }
352 }
353 foundLeft:
354 bounds.fRight = width;
355 x = width;
356 while (--x > bounds.fLeft) {
357 pixels = pixelBase + rowPixels * bounds.fTop;
358 for (y = bounds.fTop; y < bounds.fBottom; ++y) {
359 if (pixels[x]) {
360 bounds.fRight = x + 1;
361 goto foundRight;
362 }
363 pixels += rowPixels;
364 }
365 }
366 foundRight:
367 return bounds;
368 } 286 }
369 287
370 // This must be called to balance calls to cgContext 288 // This must be called to balance calls to cgContext
371 void SkiaBitLocker::releaseIfNeeded() { 289 void SkiaBitLocker::releaseIfNeeded() {
372 if (!cgContext_) 290 if (!cgContext_)
373 return; 291 return;
374 if (!useDeviceBits_ && !bitmapIsDummy_) { 292 if (!useDeviceBits_ && !bitmapIsDummy_) {
375 // Find the bits that were drawn to. 293 // Find the bits that were drawn to.
376 SkIRect bounds = computeDirtyRect(); 294 SkIRect bounds = computeDirtyRect();
377 SkBitmap subset; 295 SkBitmap subset;
(...skipping 18 matching lines...) Expand all
396 CGContextRef SkiaBitLocker::cgContext() { 314 CGContextRef SkiaBitLocker::cgContext() {
397 SkIRect clip_bounds; 315 SkIRect clip_bounds;
398 if (!canvas_->getClipDeviceBounds(&clip_bounds)) { 316 if (!canvas_->getClipDeviceBounds(&clip_bounds)) {
399 // If the clip is empty, then there is nothing to draw. The caller may 317 // If the clip is empty, then there is nothing to draw. The caller may
400 // attempt to draw (to-be-clipped) results, so ensure there is a dummy 318 // attempt to draw (to-be-clipped) results, so ensure there is a dummy
401 // non-NULL CGContext to use. 319 // non-NULL CGContext to use.
402 bitmapIsDummy_ = true; 320 bitmapIsDummy_ = true;
403 clip_bounds = SkIRect::MakeXYWH(0, 0, 1, 1); 321 clip_bounds = SkIRect::MakeXYWH(0, 0, 1, 1);
404 } 322 }
405 323
406 SkBaseDevice* device = canvas_->getTopDevice();
407 DCHECK(device);
408 if (!device)
409 return 0;
410
411 releaseIfNeeded(); // This flushes any prior bitmap use 324 releaseIfNeeded(); // This flushes any prior bitmap use
412 325
413 // remember the top/left, in case we need to compose this later 326 // remember the top/left, in case we need to compose this later
414 bitmapOffset_.set(clip_bounds.x(), clip_bounds.y()); 327 bitmapOffset_.set(clip_bounds.x(), clip_bounds.y());
415 328
416 // Now make clip_bounds be relative to the current layer/device 329 // Now make clip_bounds be relative to the current layer/device
417 clip_bounds.offset(-device->getOrigin()); 330 if (!bitmapIsDummy_) {
331 canvas_->temporary_internal_describeTopLayer(nullptr, &clip_bounds);
332 }
418 333
419 SkPixmap devicePixels; 334 SkPixmap devicePixels;
420 skia::GetWritablePixels(canvas_, &devicePixels); 335 skia::GetWritablePixels(canvas_, &devicePixels);
421 336
422 // Only draw directly if we have pixels, and we're only rect-clipped. 337 // Only draw directly if we have pixels, and we're only rect-clipped.
423 // If not, we allocate an offscreen and draw into that, relying on the 338 // If not, we allocate an offscreen and draw into that, relying on the
424 // compositing step to apply skia's clip. 339 // compositing step to apply skia's clip.
425 useDeviceBits_ = devicePixels.addr() && 340 useDeviceBits_ = devicePixels.addr() &&
426 canvas_->isClipRect() && 341 canvas_->isClipRect() &&
427 !bitmapIsDummy_; 342 !bitmapIsDummy_;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 CGContextConcatCTM(cgContext_, SkMatrixToCGAffineTransform(matrix)); 378 CGContextConcatCTM(cgContext_, SkMatrixToCGAffineTransform(matrix));
464 379
465 return cgContext_; 380 return cgContext_;
466 } 381 }
467 382
468 bool SkiaBitLocker::hasEmptyClipRegion() const { 383 bool SkiaBitLocker::hasEmptyClipRegion() const {
469 return canvas_->isClipEmpty(); 384 return canvas_->isClipEmpty();
470 } 385 }
471 386
472 } // namespace skia 387 } // namespace skia
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698