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

Side by Side Diff: third_party/WebKit/Source/platform/mac/GraphicsContextCanvas.mm

Issue 2705723002: Convert SkiaBitLocker to use PaintCanvas (Closed)
Patch Set: Remove rogue cc:: Created 3 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
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/mac/GraphicsContextCanvas.h"
6
7 #import <AppKit/AppKit.h>
8 #import <CoreGraphics/CoreGraphics.h>
9
10 #include "skia/ext/skia_utils_mac.h"
11 #include "wtf/RetainPtr.h"
12
13 namespace blink {
14
15 GraphicsContextCanvas::GraphicsContextCanvas(PaintCanvas* canvas,
16 const SkIRect& userClipRect,
17 SkScalar bitmapScaleFactor)
18 : m_canvas(canvas),
19 m_cgContext(0),
20 m_bitmapScaleFactor(bitmapScaleFactor),
21 m_useDeviceBits(false),
22 m_bitmapIsDummy(false) {
23 m_canvas->save();
24 m_canvas->clipRect(SkRect::MakeFromIRect(userClipRect));
25 }
26
27 GraphicsContextCanvas::~GraphicsContextCanvas() {
28 releaseIfNeeded();
29 m_canvas->restore();
30 }
31
32 SkIRect GraphicsContextCanvas::computeDirtyRect() {
33 // If the user specified a clip region, assume that it was tight and that the
34 // dirty rect is approximately the whole bitmap.
35 return SkIRect::MakeWH(m_offscreen.width(), m_offscreen.height());
36 }
37
38 // This must be called to balance calls to cgContext
39 void GraphicsContextCanvas::releaseIfNeeded() {
40 if (!m_cgContext)
41 return;
42 if (!m_useDeviceBits && !m_bitmapIsDummy) {
43 // Find the bits that were drawn to.
44 SkIRect bounds = computeDirtyRect();
45 SkBitmap subset;
46 if (!m_offscreen.extractSubset(&subset, bounds)) {
47 return;
48 }
49 subset.setImmutable(); // Prevents a defensive copy inside Skia.
50 m_canvas->save();
51 m_canvas->setMatrix(SkMatrix::I()); // Reset back to device space.
52 m_canvas->translate(bounds.x() + m_bitmapOffset.x(),
53 bounds.y() + m_bitmapOffset.y());
54 m_canvas->scale(1.f / m_bitmapScaleFactor, 1.f / m_bitmapScaleFactor);
55 m_canvas->drawBitmap(subset, 0, 0);
56 m_canvas->restore();
57 }
58 CGContextRelease(m_cgContext);
59 m_cgContext = 0;
60 m_useDeviceBits = false;
61 m_bitmapIsDummy = false;
62 }
63
64 CGContextRef GraphicsContextCanvas::cgContext() {
65 releaseIfNeeded(); // This flushes any prior bitmap use
66
67 SkIRect clip_bounds;
68 if (!m_canvas->getDeviceClipBounds(&clip_bounds)) {
69 // If the clip is empty, then there is nothing to draw. The caller may
70 // attempt to draw (to-be-clipped) results, so ensure there is a dummy
71 // non-NULL CGContext to use.
72 m_bitmapIsDummy = true;
73 clip_bounds = SkIRect::MakeXYWH(0, 0, 1, 1);
74 }
75
76 // remember the top/left, in case we need to compose this later
77 m_bitmapOffset.set(clip_bounds.x(), clip_bounds.y());
78
79 // Now make clip_bounds be relative to the current layer/device
80 if (!m_bitmapIsDummy) {
81 m_canvas->temporary_internal_describeTopLayer(nullptr, &clip_bounds);
82 }
83
84 SkPixmap devicePixels;
85 ToPixmap(m_canvas, &devicePixels);
86
87 // Only draw directly if we have pixels, and we're only rect-clipped.
88 // If not, we allocate an offscreen and draw into that, relying on the
89 // compositing step to apply skia's clip.
90 m_useDeviceBits =
91 devicePixels.addr() && m_canvas->isClipRect() && !m_bitmapIsDummy;
92 WTF::RetainPtr<CGColorSpace> colorSpace(CGColorSpaceCreateDeviceRGB());
93
94 int displayHeight;
95 if (m_useDeviceBits) {
96 SkPixmap subset;
97 bool result = devicePixels.extractSubset(&subset, clip_bounds);
98 DCHECK(result);
99 if (!result)
100 return 0;
101 displayHeight = subset.height();
102 m_cgContext = CGBitmapContextCreate(
103 subset.writable_addr(), subset.width(), subset.height(), 8,
104 subset.rowBytes(), colorSpace.get(),
105 kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
106 } else {
107 bool result = m_offscreen.tryAllocN32Pixels(
108 SkScalarCeilToInt(m_bitmapScaleFactor * clip_bounds.width()),
109 SkScalarCeilToInt(m_bitmapScaleFactor * clip_bounds.height()));
110 DCHECK(result);
111 if (!result)
112 return 0;
113 m_offscreen.eraseColor(0);
114 displayHeight = m_offscreen.height();
115 m_cgContext = CGBitmapContextCreate(
116 m_offscreen.getPixels(), m_offscreen.width(), m_offscreen.height(), 8,
117 m_offscreen.rowBytes(), colorSpace.get(),
118 kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
119 }
120 DCHECK(m_cgContext);
121
122 SkMatrix matrix = m_canvas->getTotalMatrix();
123 matrix.postTranslate(-SkIntToScalar(m_bitmapOffset.x()),
124 -SkIntToScalar(m_bitmapOffset.y()));
125 matrix.postScale(m_bitmapScaleFactor, -m_bitmapScaleFactor);
126 matrix.postTranslate(0, SkIntToScalar(displayHeight));
127
128 CGContextConcatCTM(m_cgContext, skia::SkMatrixToCGAffineTransform(matrix));
129
130 return m_cgContext;
131 }
132
133 bool GraphicsContextCanvas::hasEmptyClipRegion() const {
134 return m_canvas->isClipEmpty();
135 }
136
137 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698