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

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

Issue 1963713002: Replace setMatrixClip() with BeginPlatformPaint() logic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: compensate for any outstanding saveLayer() calls 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 | « skia/ext/bitmap_platform_device_mac.h ('k') | skia/ext/bitmap_platform_device_mac_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) 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/bitmap_platform_device_mac.h" 5 #include "skia/ext/bitmap_platform_device_mac.h"
6 6
7 #import <ApplicationServices/ApplicationServices.h> 7 #import <ApplicationServices/ApplicationServices.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <time.h> 9 #include <time.h>
10 10
11 #include "base/mac/mac_util.h" 11 #include "base/mac/mac_util.h"
12 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
13 #include "skia/ext/bitmap_platform_device.h" 13 #include "skia/ext/bitmap_platform_device.h"
14 #include "skia/ext/platform_canvas.h" 14 #include "skia/ext/platform_canvas.h"
15 #include "skia/ext/skia_utils_mac.h" 15 #include "skia/ext/skia_utils_mac.h"
16 #include "third_party/skia/include/core/SkMatrix.h" 16 #include "third_party/skia/include/core/SkMatrix.h"
17 #include "third_party/skia/include/core/SkPath.h" 17 #include "third_party/skia/include/core/SkPath.h"
18 #include "third_party/skia/include/core/SkRegion.h" 18 #include "third_party/skia/include/core/SkRect.h"
19 #include "third_party/skia/include/core/SkTypes.h" 19 #include "third_party/skia/include/core/SkTypes.h"
20 20
21 namespace skia { 21 namespace skia {
22 22
23 namespace { 23 namespace {
24 24
25 // Returns true if it is unsafe to attempt to allocate an offscreen buffer 25 // Returns true if it is unsafe to attempt to allocate an offscreen buffer
26 // given these dimensions. 26 // given these dimensions.
27 bool RasterDeviceTooBigToAllocate(int width, int height) { 27 bool RasterDeviceTooBigToAllocate(int width, int height) {
28 28
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 } 70 }
71 71
72 } // namespace 72 } // namespace
73 73
74 void BitmapPlatformDevice::ReleaseBitmapContext() { 74 void BitmapPlatformDevice::ReleaseBitmapContext() {
75 SkASSERT(bitmap_context_); 75 SkASSERT(bitmap_context_);
76 CGContextRelease(bitmap_context_); 76 CGContextRelease(bitmap_context_);
77 bitmap_context_ = NULL; 77 bitmap_context_ = NULL;
78 } 78 }
79 79
80 void BitmapPlatformDevice::SetMatrixClip(
81 const SkMatrix& transform,
82 const SkRegion& region) {
83 transform_ = transform;
84 clip_region_ = region;
85 config_dirty_ = true;
86 }
87
88 // Loads the specified Skia transform into the device context 80 // Loads the specified Skia transform into the device context
89 static void LoadTransformToCGContext(CGContextRef context, 81 static void LoadTransformToCGContext(CGContextRef context,
90 const SkMatrix& matrix) { 82 const SkMatrix& matrix) {
91 // CoreGraphics can concatenate transforms, but not reset the current one. 83 // CoreGraphics can concatenate transforms, but not reset the current one.
92 // So in order to get the required behavior here, we need to first make 84 // So in order to get the required behavior here, we need to first make
93 // the current transformation matrix identity and only then load the new one. 85 // the current transformation matrix identity and only then load the new one.
94 86
95 // Reset matrix to identity. 87 // Reset matrix to identity.
96 CGAffineTransform orig_cg_matrix = CGContextGetCTM(context); 88 CGAffineTransform orig_cg_matrix = CGContextGetCTM(context);
97 CGAffineTransform orig_cg_matrix_inv = 89 CGAffineTransform orig_cg_matrix_inv =
(...skipping 13 matching lines...) Expand all
111 SkScalar ty = -matrix.getTranslateY(); // y axis is flipped. 103 SkScalar ty = -matrix.getTranslateY(); // y axis is flipped.
112 transformed_matrix.setTranslateY(ty + (SkScalar)height); 104 transformed_matrix.setTranslateY(ty + (SkScalar)height);
113 105
114 CGAffineTransform cg_matrix = 106 CGAffineTransform cg_matrix =
115 skia::SkMatrixToCGAffineTransform(transformed_matrix); 107 skia::SkMatrixToCGAffineTransform(transformed_matrix);
116 108
117 // Load final transform into context. 109 // Load final transform into context.
118 CGContextConcatCTM(context, cg_matrix); 110 CGContextConcatCTM(context, cg_matrix);
119 } 111 }
120 112
121 // Loads a SkRegion into the CG context.
122 static void LoadClippingRegionToCGContext(CGContextRef context, 113 static void LoadClippingRegionToCGContext(CGContextRef context,
123 const SkRegion& region, 114 const SkIRect& clip_bounds,
124 const SkMatrix& transformation) { 115 const SkMatrix& transformation) {
125 if (region.isEmpty()) { 116 // CoreGraphics applies the current transform to clip rects, which is
126 // region can be empty, in which case everything will be clipped. 117 // unwanted. Inverse-transform the rect before sending it to CG. This only
127 SkRect rect; 118 // works for translations and scaling, but not for rotations (but the
128 rect.setEmpty(); 119 // viewport is never rotated anyway).
129 CGContextClipToRect(context, skia::SkRectToCGRect(rect)); 120 SkMatrix t;
130 } else if (region.isRect()) { 121 bool did_invert = transformation.invert(&t);
131 // CoreGraphics applies the current transform to clip rects, which is 122 if (!did_invert)
132 // unwanted. Inverse-transform the rect before sending it to CG. This only 123 t.reset();
133 // works for translations and scaling, but not for rotations (but the 124
134 // viewport is never rotated anyway). 125 SkRect rect = SkRect::Make(clip_bounds);
135 SkMatrix t; 126 t.mapRect(&rect);
136 bool did_invert = transformation.invert(&t); 127 SkIRect irect;
137 if (!did_invert) 128 rect.round(&irect);
138 t.reset(); 129 CGContextClipToRect(context, skia::SkIRectToCGRect(irect));
139 // Do the transformation.
140 SkRect rect;
141 rect.set(region.getBounds());
142 t.mapRect(&rect);
143 SkIRect irect;
144 rect.round(&irect);
145 CGContextClipToRect(context, skia::SkIRectToCGRect(irect));
146 } else {
147 // It is complex.
148 SkPath path;
149 region.getBoundaryPath(&path);
150 // Clip. Note that windows clipping regions are not affected by the
151 // transform so apply it manually.
152 path.transform(transformation);
153 // TODO(playmobil): Implement.
154 SkASSERT(false);
155 // LoadPathToDC(context, path);
156 // hrgn = PathToRegion(context);
157 }
158 } 130 }
159 131
160 void BitmapPlatformDevice::LoadConfig() { 132 void BitmapPlatformDevice::LoadConfig(const SkMatrix& transform,
161 if (!config_dirty_ || !bitmap_context_) 133 const SkIRect& clip_bounds) {
134 if (!bitmap_context_)
162 return; // Nothing to do. 135 return; // Nothing to do.
163 config_dirty_ = false;
164 136
165 // We must restore and then save the state of the graphics context since the 137 // We must restore and then save the state of the graphics context since the
166 // calls to Load the clipping region to the context are strictly cummulative, 138 // calls to Load the clipping region to the context are strictly cummulative,
167 // i.e., you can't replace a clip rect, other than with a save/restore. 139 // i.e., you can't replace a clip rect, other than with a save/restore.
168 // But this implies that no other changes to the state are done elsewhere. 140 // But this implies that no other changes to the state are done elsewhere.
169 // If we ever get to need to change this, then we must replace the clip rect 141 // If we ever get to need to change this, then we must replace the clip rect
170 // calls in LoadClippingRegionToCGContext() with an image mask instead. 142 // calls in LoadClippingRegionToCGContext() with an image mask instead.
171 CGContextRestoreGState(bitmap_context_); 143 CGContextRestoreGState(bitmap_context_);
172 CGContextSaveGState(bitmap_context_); 144 CGContextSaveGState(bitmap_context_);
173 LoadTransformToCGContext(bitmap_context_, transform_); 145 LoadTransformToCGContext(bitmap_context_, transform);
174 LoadClippingRegionToCGContext(bitmap_context_, clip_region_, transform_); 146 LoadClippingRegionToCGContext(bitmap_context_, clip_bounds, transform);
175 } 147 }
176 148
177 149
178 // We use this static factory function instead of the regular constructor so 150 // We use this static factory function instead of the regular constructor so
179 // that we can create the pixel data before calling the constructor. This is 151 // that we can create the pixel data before calling the constructor. This is
180 // required so that we can call the base class' constructor with the pixel 152 // required so that we can call the base class' constructor with the pixel
181 // data. 153 // data.
182 BitmapPlatformDevice* BitmapPlatformDevice::Create(CGContextRef context, 154 BitmapPlatformDevice* BitmapPlatformDevice::Create(CGContextRef context,
183 int width, 155 int width,
184 int height, 156 int height,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 CGContextRelease(context); 217 CGContextRelease(context);
246 218
247 return rv; 219 return rv;
248 } 220 }
249 221
250 // The device will own the bitmap, which corresponds to also owning the pixel 222 // The device will own the bitmap, which corresponds to also owning the pixel
251 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap. 223 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap.
252 BitmapPlatformDevice::BitmapPlatformDevice( 224 BitmapPlatformDevice::BitmapPlatformDevice(
253 CGContextRef context, const SkBitmap& bitmap) 225 CGContextRef context, const SkBitmap& bitmap)
254 : SkBitmapDevice(bitmap), 226 : SkBitmapDevice(bitmap),
255 bitmap_context_(context), 227 bitmap_context_(context) {
256 config_dirty_(true), // Want to load the config next time.
257 transform_(SkMatrix::I()) {
258 SetPlatformDevice(this, this); 228 SetPlatformDevice(this, this);
259 SkASSERT(bitmap_context_); 229 SkASSERT(bitmap_context_);
260 // Initialize the clip region to the entire bitmap. 230 // Initialize the clip region to the entire bitmap.
261 231
262 SkIRect rect; 232 SkIRect rect;
263 rect.set(0, 0, 233 rect.set(0, 0,
264 CGBitmapContextGetWidth(bitmap_context_), 234 CGBitmapContextGetWidth(bitmap_context_),
265 CGBitmapContextGetHeight(bitmap_context_)); 235 CGBitmapContextGetHeight(bitmap_context_));
266 clip_region_ = SkRegion(rect);
267 CGContextRetain(bitmap_context_); 236 CGContextRetain(bitmap_context_);
268 // We must save the state once so that we can use the restore/save trick 237 // We must save the state once so that we can use the restore/save trick
269 // in LoadConfig(). 238 // in LoadConfig().
270 CGContextSaveGState(bitmap_context_); 239 CGContextSaveGState(bitmap_context_);
271 } 240 }
272 241
273 BitmapPlatformDevice::~BitmapPlatformDevice() { 242 BitmapPlatformDevice::~BitmapPlatformDevice() {
274 if (bitmap_context_) 243 if (bitmap_context_)
275 CGContextRelease(bitmap_context_); 244 CGContextRelease(bitmap_context_);
276 } 245 }
277 246
278 CGContextRef BitmapPlatformDevice::GetBitmapContext() { 247 CGContextRef BitmapPlatformDevice::GetBitmapContext(const SkMatrix& transform,
279 LoadConfig(); 248 const SkIRect& clip_bounds) {
249 LoadConfig(transform, clip_bounds);
280 return bitmap_context_; 250 return bitmap_context_;
281 } 251 }
282 252
283 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
284 const SkRegion& region,
285 const SkClipStack&) {
286 SetMatrixClip(transform, region);
287 }
288
289 SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo, 253 SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const CreateInfo& cinfo,
290 const SkPaint*) { 254 const SkPaint*) {
291 const SkImageInfo& info = cinfo.fInfo; 255 const SkImageInfo& info = cinfo.fInfo;
292 const bool do_clear = !info.isOpaque(); 256 const bool do_clear = !info.isOpaque();
293 SkASSERT(info.colorType() == kN32_SkColorType); 257 SkASSERT(info.colorType() == kN32_SkColorType);
294 return Create(NULL, info.width(), info.height(), info.isOpaque(), do_clear); 258 return Create(NULL, info.width(), info.height(), info.isOpaque(), do_clear);
295 } 259 }
296 260
297 // PlatformCanvas impl 261 // PlatformCanvas impl
298 262
299 SkCanvas* CreatePlatformCanvas(CGContextRef ctx, int width, int height, 263 SkCanvas* CreatePlatformCanvas(CGContextRef ctx, int width, int height,
300 bool is_opaque, OnFailureType failureType) { 264 bool is_opaque, OnFailureType failureType) {
301 const bool do_clear = false; 265 const bool do_clear = false;
302 sk_sp<SkBaseDevice> dev( 266 sk_sp<SkBaseDevice> dev(
303 BitmapPlatformDevice::Create(ctx, width, height, is_opaque, do_clear)); 267 BitmapPlatformDevice::Create(ctx, width, height, is_opaque, do_clear));
304 return CreateCanvas(dev, failureType); 268 return CreateCanvas(dev, failureType);
305 } 269 }
306 270
307 SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque, 271 SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque,
308 uint8_t* data, OnFailureType failureType) { 272 uint8_t* data, OnFailureType failureType) {
309 sk_sp<SkBaseDevice> dev( 273 sk_sp<SkBaseDevice> dev(
310 BitmapPlatformDevice::CreateWithData(data, width, height, is_opaque)); 274 BitmapPlatformDevice::CreateWithData(data, width, height, is_opaque));
311 return CreateCanvas(dev, failureType); 275 return CreateCanvas(dev, failureType);
312 } 276 }
313 277
314 } // namespace skia 278 } // namespace skia
OLDNEW
« no previous file with comments | « skia/ext/bitmap_platform_device_mac.h ('k') | skia/ext/bitmap_platform_device_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698