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

Side by Side Diff: src/gpu/GrOvalRenderer.cpp

Issue 12657003: Move oval rendering code to GrOvalRenderer (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Added some line wraps Created 7 years, 9 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 | Annotate | Revision Log
« src/gpu/GrContext.cpp ('K') | « src/gpu/GrContext.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
robertphillips 2013/03/21 13:12:39 2013
jvanverth1 2013/03/21 18:42:18 Done.
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrOvalRenderer.h"
9
10 #include "effects/GrCircleEdgeEffect.h"
11 #include "effects/GrEllipseEdgeEffect.h"
12
13 #include "GrContext.h"
14 #include "GrDrawState.h"
15 #include "GrDrawTarget.h"
16 #include "GrPaint.h"
17 #include "SkStrokeRec.h"
18
19 SK_DEFINE_INST_COUNT(GrOvalRenderer)
20
21 namespace {
22
23 struct CircleVertex {
24 GrPoint fPos;
25 GrPoint fCenter;
26 SkScalar fOuterRadius;
27 SkScalar fInnerRadius;
28 };
29
30 struct EllipseVertex {
31 GrPoint fPos;
32 GrPoint fCenter;
33 SkScalar fOuterXRadius;
34 SkScalar fOuterXYRatio;
35 SkScalar fInnerXRadius;
36 SkScalar fInnerXYRatio;
37 };
38
robertphillips 2013/03/21 13:12:39 circle_stays_circle
jvanverth1 2013/03/21 18:42:18 Done.
39 inline bool circleStaysCircle(const SkMatrix& m) {
40 return m.isSimilarity();
41 }
42
43 }
44
45 bool GrOvalRenderer::canDrawOval(const GrContext* context, const GrPaint& paint,
46 const GrRect& oval, bool* isCircle) const
47 {
48 GrAssert(isCircle != NULL);
49
50 if (!paint.isAntiAlias()) {
51 return false;
52 }
53
54 // we can draw circles
55 *isCircle = SkScalarNearlyEqual(oval.width(), oval.height())
56 && circleStaysCircle(context->getMatrix());
57 // and axis-aligned ellipses only
58 bool isAxisAlignedEllipse = context->getMatrix().rectStaysRect();
59
60 return *isCircle || isAxisAlignedEllipse;
61
62 }
63
64 void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
65 const GrPaint& paint,
66 const GrRect& ellipse,
67 const SkStrokeRec& stroke)
68 {
69 GrDrawState* drawState = target->drawState();
70 #ifdef SK_DEBUG
71 {
72 // we should have checked for this previously
73 bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
74 SkASSERT(paint.isAntiAlias() && isAxisAlignedEllipse);
75 }
76 #endif
77
robertphillips 2013/03/21 13:12:39 Do we even need "rt"?
jvanverth1 2013/03/21 18:42:18 Done.
78 const GrRenderTarget* rt = drawState->getRenderTarget();
79 if (NULL == rt) {
80 return;
81 }
82
robertphillips 2013/03/21 13:12:39 &
jvanverth1 2013/03/21 18:42:18 Done.
83 const SkMatrix vm = drawState->getViewMatrix();
84
85 GrDrawState::AutoDeviceCoordDraw adcd(drawState);
86 if (!adcd.succeeded()) {
87 return;
88 }
89
90 // position + edge
91 static const GrVertexAttrib kVertexAttribs[] = {
92 {kVec2f_GrVertexAttribType, 0},
93 {kVec2f_GrVertexAttribType, sizeof(GrPoint)},
94 {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint)}
95 };
96 drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
97 drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
98 GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize());
99
100 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
101 if (!geo.succeeded()) {
102 GrPrintf("Failed to get space for vertices!\n");
103 return;
104 }
105
106 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
107
108 GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
109 vm.mapPoints(&center, 1);
110
111 SkStrokeRec::Style style = stroke.getStyle();
112 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style);
113 enum {
114 // the edge effects share this stage with glyph rendering
115 // (kGlyphMaskStage in GrTextContext) && SW path rendering
116 // (kPathMaskStage in GrSWMaskHelper)
117 kEdgeEffectStage = GrPaint::kTotalStages,
118 };
119 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
120
121 GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked);
122 static const int kEllipseCenterAttrIndex = 1;
123 static const int kEllipseEdgeAttrIndex = 2;
124 drawState->setEffect(kEdgeEffectStage, effect,
125 kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref( );
126
127 SkRect xformedRect;
128 vm.mapRect(&xformedRect, ellipse);
129
130 SkScalar xRadius = SkScalarHalf(xformedRect.width());
131 SkScalar yRadius = SkScalarHalf(xformedRect.height());
132 SkScalar innerXRadius = 0.0f;
133 SkScalar innerRatio = 1.0f;
134
135 if (SkStrokeRec::kFill_Style != style) {
136 SkScalar strokeWidth = stroke.getWidth();
137
138 // do (potentially) anisotropic mapping
139 SkVector scaledStroke;
140 scaledStroke.set(strokeWidth, strokeWidth);
141 vm.mapVectors(&scaledStroke, 1);
142
143 if (SkScalarNearlyZero(scaledStroke.length())) {
144 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
145 } else {
146 scaledStroke.scale(0.5f);
147 }
148
149 // this is legit only if scale & translation (which should be the case a t the moment)
150 if (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style) {
151 SkScalar innerYRadius = SkMaxScalar(0, yRadius - scaledStroke.fY);
152 if (innerYRadius > SK_ScalarNearlyZero) {
153 innerXRadius = SkMaxScalar(0, xRadius - scaledStroke.fX);
154 innerRatio = innerXRadius/innerYRadius;
155 }
156 }
157 xRadius += scaledStroke.fX;
158 yRadius += scaledStroke.fY;
159 }
160
161 SkScalar outerRatio = SkScalarDiv(xRadius, yRadius);
162
163 for (int i = 0; i < 4; ++i) {
164 verts[i].fCenter = center;
165 verts[i].fOuterXRadius = xRadius + 0.5f;
166 verts[i].fOuterXYRatio = outerRatio;
167 verts[i].fInnerXRadius = innerXRadius - 0.5f;
168 verts[i].fInnerXYRatio = innerRatio;
169 }
170
171 SkScalar L = -xRadius;
172 SkScalar R = +xRadius;
173 SkScalar T = -yRadius;
174 SkScalar B = +yRadius;
175
176 // We've extended the outer x radius out half a pixel to antialias.
177 // Expand the drawn rect here so all the pixels will be captured.
178 L += center.fX - SK_ScalarHalf;
179 R += center.fX + SK_ScalarHalf;
180 T += center.fY - SK_ScalarHalf;
181 B += center.fY + SK_ScalarHalf;
182
183 verts[0].fPos = SkPoint::Make(L, T);
184 verts[1].fPos = SkPoint::Make(R, T);
185 verts[2].fPos = SkPoint::Make(L, B);
186 verts[3].fPos = SkPoint::Make(R, B);
187
188 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
189 }
190
191 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
192 const GrPaint& paint,
193 const GrRect& circle,
194 const SkStrokeRec& stroke)
195 {
196 GrDrawState* drawState = target->drawState();
robertphillips 2013/03/21 13:12:39 Do we even need "rt"?
jvanverth1 2013/03/21 18:42:18 Done.
197 const GrRenderTarget* rt = drawState->getRenderTarget();
198 if (NULL == rt) {
199 return;
200 }
201
202 SkScalar radius = SkScalarHalf(circle.width());
203
204 SkScalar strokeWidth = stroke.getWidth();
205 SkStrokeRec::Style style = stroke.getStyle();
206
robertphillips 2013/03/21 13:12:39 &
jvanverth1 2013/03/21 18:42:18 Done.
207 const SkMatrix vm = drawState->getViewMatrix();
208
209 GrDrawState::AutoDeviceCoordDraw adcd(drawState);
210 if (!adcd.succeeded()) {
211 return;
212 }
213
214 // position + edge
215 static const GrVertexAttrib kVertexAttribs[] = {
216 {kVec2f_GrVertexAttribType, 0},
217 {kVec4f_GrVertexAttribType, sizeof(GrPoint)}
218 };
219 drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
220 drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
221 GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
222
223 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
224 if (!geo.succeeded()) {
225 GrPrintf("Failed to get space for vertices!\n");
226 return;
227 }
228
229 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
230
231 GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY());
232 vm.mapPoints(&center, 1);
233
234 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style);
235 enum {
236 // the edge effects share this stage with glyph rendering
237 // (kGlyphMaskStage in GrTextContext) && SW path rendering
238 // (kPathMaskStage in GrSWMaskHelper)
239 kEdgeEffectStage = GrPaint::kTotalStages,
240 };
241 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
242
243 GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked);
244 static const int kCircleEdgeAttrIndex = 1;
245 drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref( );
246
247 radius = vm.mapRadius(radius);
248
249 SkScalar innerRadius = 0.0f;
250 SkScalar outerRadius = radius;
251 SkScalar halfWidth = 0;
252 if (style != SkStrokeRec::kFill_Style) {
253 strokeWidth = vm.mapRadius(strokeWidth);
254 if (SkScalarNearlyZero(strokeWidth)) {
255 halfWidth = SK_ScalarHalf;
256 } else {
257 halfWidth = SkScalarHalf(strokeWidth);
258 }
259
260 outerRadius += halfWidth;
261 if (isStroked) {
262 innerRadius = SkMaxScalar(0, radius - halfWidth);
263 }
264 }
265
266 for (int i = 0; i < 4; ++i) {
267 verts[i].fCenter = center;
268 verts[i].fOuterRadius = outerRadius + 0.5f;
269 verts[i].fInnerRadius = innerRadius - 0.5f;
270 }
271
272 SkScalar L = -outerRadius;
273 SkScalar R = +outerRadius;
274 SkScalar T = -outerRadius;
275 SkScalar B = +outerRadius;
276
277 // We've extended the outer radius out half a pixel to antialias.
278 // Expand the drawn rect here so all the pixels will be captured.
279 L += center.fX - SK_ScalarHalf;
280 R += center.fX + SK_ScalarHalf;
281 T += center.fY - SK_ScalarHalf;
282 B += center.fY + SK_ScalarHalf;
283
284 verts[0].fPos = SkPoint::Make(L, T);
285 verts[1].fPos = SkPoint::Make(R, T);
286 verts[2].fPos = SkPoint::Make(L, B);
287 verts[3].fPos = SkPoint::Make(R, B);
288
289 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
290 }
OLDNEW
« src/gpu/GrContext.cpp ('K') | « src/gpu/GrContext.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698