OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/gfx/platform_device_mac.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/gfx/skia_utils_mac.h" | |
9 #include "SkMatrix.h" | |
10 #include "SkPath.h" | |
11 #include "SkUtils.h" | |
12 | |
13 namespace gfx { | |
14 | |
15 namespace { | |
16 | |
17 // Constrains position and size to fit within available_size. | |
18 bool constrain(int available_size, int* position, int *size) { | |
19 if (*position < 0) { | |
20 *size += *position; | |
21 *position = 0; | |
22 } | |
23 if (*size > 0 && *position < available_size) { | |
24 int overflow = (*position + *size) - available_size; | |
25 if (overflow > 0) { | |
26 *size -= overflow; | |
27 } | |
28 return true; | |
29 } | |
30 return false; | |
31 } | |
32 | |
33 // Sets the opacity of the specified value to 0xFF. | |
34 void makeOpaqueAlphaAdjuster(uint32_t* pixel) { | |
35 *pixel |= 0xFF000000; | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 PlatformDeviceMac::PlatformDeviceMac(const SkBitmap& bitmap) | |
41 : SkDevice(bitmap) { | |
42 } | |
43 | |
44 void PlatformDeviceMac::makeOpaque(int x, int y, int width, int height) { | |
45 processPixels(x, y, width, height, makeOpaqueAlphaAdjuster); | |
46 } | |
47 | |
48 // Set up the CGContextRef for peaceful coexistence with Skia | |
49 void PlatformDeviceMac::InitializeCGContext(CGContextRef context) { | |
50 // CG defaults to the same settings as Skia | |
51 } | |
52 | |
53 // static | |
54 void PlatformDeviceMac::LoadPathToCGContext(CGContextRef context, | |
55 const SkPath& path) { | |
56 // instead of a persistent attribute of the context, CG specifies the fill | |
57 // type per call, so we just have to load up the geometry. | |
58 CGContextBeginPath(context); | |
59 | |
60 SkPoint points[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; | |
61 SkPath::Iter iter(path, false); | |
62 for (SkPath::Verb verb = iter.next(points); verb != SkPath::kDone_Verb; | |
63 verb = iter.next(points)) { | |
64 switch (verb) { | |
65 case SkPath::kMove_Verb: { // iter.next returns 1 point | |
66 CGContextMoveToPoint(context, points[0].fX, points[0].fY); | |
67 break; | |
68 } | |
69 case SkPath::kLine_Verb: { // iter.next returns 2 points | |
70 CGContextAddLineToPoint(context, points[1].fX, points[1].fY); | |
71 break; | |
72 } | |
73 case SkPath::kQuad_Verb: { // iter.next returns 3 points | |
74 CGContextAddQuadCurveToPoint(context, points[1].fX, points[1].fY, | |
75 points[2].fX, points[2].fY); | |
76 break; | |
77 } | |
78 case SkPath::kCubic_Verb: { // iter.next returns 4 points | |
79 CGContextAddCurveToPoint(context, points[1].fX, points[1].fY, | |
80 points[2].fX, points[2].fY, | |
81 points[3].fX, points[3].fY); | |
82 break; | |
83 } | |
84 case SkPath::kClose_Verb: { // iter.next returns 1 point (the last point) | |
85 break; | |
86 } | |
87 case SkPath::kDone_Verb: // iter.next returns 0 points | |
88 default: { | |
89 NOTREACHED(); | |
90 break; | |
91 } | |
92 } | |
93 } | |
94 CGContextClosePath(context); | |
95 } | |
96 | |
97 // static | |
98 void PlatformDeviceMac::LoadTransformToCGContext(CGContextRef context, | |
99 const SkMatrix& matrix) { | |
100 // CoreGraphics can concatenate transforms, but not reset the current one. | |
101 // So in order to get the required behavior here, we need to first make | |
102 // the current transformation matrix identity and only then load the new one. | |
103 | |
104 // Reset matrix to identity. | |
105 CGAffineTransform orig_cg_matrix = CGContextGetCTM(context); | |
106 CGAffineTransform orig_cg_matrix_inv = CGAffineTransformInvert(orig_cg_matrix)
; | |
107 CGContextConcatCTM(context, orig_cg_matrix_inv); | |
108 | |
109 // assert that we have indeed returned to the identity Matrix. | |
110 DCHECK(CGAffineTransformIsIdentity(CGContextGetCTM(context))); | |
111 | |
112 // Convert xform to CG-land. | |
113 // Our coordinate system is flipped to match WebKit's so we need to modify | |
114 // the xform to match that. | |
115 SkMatrix transformed_matrix = matrix; | |
116 SkScalar sy = matrix.getScaleY() * (SkScalar)-1; | |
117 transformed_matrix.setScaleY(sy); | |
118 size_t height = CGBitmapContextGetHeight(context); | |
119 SkScalar ty = -matrix.getTranslateY(); // y axis is flipped. | |
120 transformed_matrix.setTranslateY(ty + (SkScalar)height); | |
121 | |
122 CGAffineTransform cg_matrix = SkMatrixToCGAffineTransform(transformed_matrix); | |
123 | |
124 // Load final transform into context. | |
125 CGContextConcatCTM(context, cg_matrix); | |
126 } | |
127 | |
128 // static | |
129 void PlatformDeviceMac::LoadClippingRegionToCGContext( | |
130 CGContextRef context, | |
131 const SkRegion& region, | |
132 const SkMatrix& transformation) { | |
133 if (region.isEmpty()) { | |
134 // region can be empty, in which case everything will be clipped. | |
135 SkRect rect; | |
136 rect.setEmpty(); | |
137 CGContextClipToRect(context, SkRectToCGRect(rect)); | |
138 } else if (region.isRect()) { | |
139 // Do the transformation. | |
140 SkRect rect; | |
141 rect.set(region.getBounds()); | |
142 transformation.mapRect(&rect); | |
143 SkIRect irect; | |
144 rect.round(&irect); | |
145 CGContextClipToRect(context, 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 NOTREACHED(); | |
155 // LoadPathToDC(context, path); | |
156 // hrgn = PathToRegion(context); | |
157 } | |
158 } | |
159 | |
160 } // namespace gfx | |
161 | |
OLD | NEW |