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