OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrAARectRenderer.h" | 8 #include "GrAARectRenderer.h" |
9 #include "GrGpu.h" | 9 #include "GrGpu.h" |
10 #include "gl/builders/GrGLProgramBuilder.h" | 10 #include "gl/builders/GrGLProgramBuilder.h" |
11 #include "gl/GrGLProcessor.h" | 11 #include "gl/GrGLProcessor.h" |
12 #include "gl/GrGLGeometryProcessor.h" | 12 #include "gl/GrGLGeometryProcessor.h" |
13 #include "GrTBackendProcessorFactory.h" | 13 #include "GrTBackendProcessorFactory.h" |
14 #include "SkColorPriv.h" | 14 #include "SkColorPriv.h" |
15 #include "GrGeometryProcessor.h" | 15 #include "GrGeometryProcessor.h" |
16 | 16 |
17 /////////////////////////////////////////////////////////////////////////////// | 17 /////////////////////////////////////////////////////////////////////////////// |
18 class GrGLAlignedRectEffect; | |
19 | |
20 // Axis Aligned special case | |
21 class GrAlignedRectEffect : public GrGeometryProcessor { | |
22 public: | |
23 static GrGeometryProcessor* Create() { | |
24 GR_CREATE_STATIC_PROCESSOR(gAlignedRectEffect, GrAlignedRectEffect, ()); | |
25 gAlignedRectEffect->ref(); | |
26 return gAlignedRectEffect; | |
27 } | |
28 | |
29 virtual ~GrAlignedRectEffect() {} | |
30 | |
31 static const char* Name() { return "AlignedRectEdge"; } | |
32 | |
33 const GrShaderVar& inRect() const { return fInRect; } | |
34 | |
35 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | |
36 return GrTBackendGeometryProcessorFactory<GrAlignedRectEffect>::getInsta
nce(); | |
37 } | |
38 | |
39 class GLProcessor : public GrGLGeometryProcessor { | |
40 public: | |
41 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | |
42 : INHERITED (factory) {} | |
43 | |
44 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | |
45 // setup the varying for the Axis aligned rect effect | |
46 // xy -> interpolated offset | |
47 // zw -> w/2+0.5, h/2+0.5 | |
48 GrGLVertToFrag v(kVec4f_GrSLType); | |
49 args.fPB->addVarying("Rect", &v); | |
50 | |
51 const GrShaderVar& inRect = args.fGP.cast<GrAlignedRectEffect>().inR
ect(); | |
52 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
53 vsBuilder->codeAppendf("\t%s = %s;\n", v.fsIn(), inRect.c_str()); | |
54 | |
55 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | |
56 // TODO: compute all these offsets, spans, and scales in the VS | |
57 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", v
.fsIn()); | |
58 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", v
.fsIn()); | |
59 fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); | |
60 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0
). For rects | |
61 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a
0 .. 1 range. | |
62 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); | |
63 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); | |
64 // For rects < 1 pixel wide or tall, these scale factors are used to
cap the maximum | |
65 // value of coverage that is used. In other words it is the coverage
that is | |
66 // used in the interior of the rect after the ramp. | |
67 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\
n"); | |
68 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\
n"); | |
69 | |
70 // Compute the coverage for the rect's width | |
71 fsBuilder->codeAppendf( | |
72 "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.
0);\n", v.fsIn(), | |
73 v.fsIn()); | |
74 // Compute the coverage for the rect's height and merge with the wid
th | |
75 fsBuilder->codeAppendf( | |
76 "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0,
1.0);\n", | |
77 v.fsIn(), v.fsIn()); | |
78 | |
79 | |
80 fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, | |
81 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("cove
rage")).c_str()); | |
82 } | |
83 | |
84 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBu
ilder*) {} | |
85 | |
86 virtual void setData(const GrGLProgramDataManager& pdman, const GrProces
sor&) SK_OVERRIDE {} | |
87 | |
88 private: | |
89 typedef GrGLGeometryProcessor INHERITED; | |
90 }; | |
91 | |
92 | |
93 private: | |
94 GrAlignedRectEffect() | |
95 : fInRect(this->addVertexAttrib(GrShaderVar("inRect", | |
96 kVec4f_GrSLType, | |
97 GrShaderVar::kAttribute_Type
Modifier))) { | |
98 } | |
99 | |
100 const GrShaderVar& fInRect; | |
101 | |
102 virtual bool onIsEqual(const GrGeometryProcessor&) const SK_OVERRIDE { retur
n true; } | |
103 | |
104 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERR
IDE { | |
105 inout->mulByUnknownAlpha(); | |
106 } | |
107 | |
108 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | |
109 | |
110 typedef GrGeometryProcessor INHERITED; | |
111 }; | |
112 | |
113 | |
114 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrAlignedRectEffect); | |
115 | |
116 GrGeometryProcessor* GrAlignedRectEffect::TestCreate(SkRandom* random, | |
117 GrContext* context, | |
118 const GrDrawTargetCaps&, | |
119 GrTexture* textures[]) { | |
120 return GrAlignedRectEffect::Create(); | |
121 } | |
122 | |
123 /////////////////////////////////////////////////////////////////////////////// | |
124 class GrGLRectEffect; | |
125 | |
126 /** | |
127 * The output of this effect is a modulation of the input color and coverage | |
128 * for an arbitrarily oriented rect. The rect is specified as: | |
129 * Center of the rect | |
130 * Unit vector point down the height of the rect | |
131 * Half width + 0.5 | |
132 * Half height + 0.5 | |
133 * The center and vector are stored in a vec4 varying ("RectEdge") with the | |
134 * center in the xy components and the vector in the zw components. | |
135 * The munged width and height are stored in a vec2 varying ("WidthHeight") | |
136 * with the width in x and the height in y. | |
137 */ | |
138 | |
139 class GrRectEffect : public GrGeometryProcessor { | |
140 public: | |
141 static GrGeometryProcessor* Create() { | |
142 GR_CREATE_STATIC_PROCESSOR(gRectEffect, GrRectEffect, ()); | |
143 gRectEffect->ref(); | |
144 return gRectEffect; | |
145 } | |
146 | |
147 virtual ~GrRectEffect() {} | |
148 | |
149 static const char* Name() { return "RectEdge"; } | |
150 | |
151 const GrShaderVar& inRectEdge() const { return fInRectEdge; } | |
152 const GrShaderVar& inWidthHeight() const { return fInWidthHeight; } | |
153 | |
154 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | |
155 return GrTBackendGeometryProcessorFactory<GrRectEffect>::getInstance(); | |
156 } | |
157 | |
158 class GLProcessor : public GrGLGeometryProcessor { | |
159 public: | |
160 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | |
161 : INHERITED (factory) {} | |
162 | |
163 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | |
164 // setup the varying for the center point and the unit vector | |
165 // that points down the height of the rect | |
166 GrGLVertToFrag rectEdge(kVec4f_GrSLType); | |
167 args.fPB->addVarying("RectEdge", &rectEdge); | |
168 | |
169 const GrRectEffect& rectEffect = args.fGP.cast<GrRectEffect>(); | |
170 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
171 vsBuilder->codeAppendf("%s = %s;", rectEdge.vsOut(), rectEffect.inRe
ctEdge().c_str()); | |
172 | |
173 // setup the varying for width/2+.5 and height/2+.5 | |
174 GrGLVertToFrag widthHeight(kVec2f_GrSLType); | |
175 args.fPB->addVarying("WidthHeight", &widthHeight); | |
176 vsBuilder->codeAppendf("%s = %s;", | |
177 widthHeight.vsOut(), | |
178 rectEffect.inWidthHeight().c_str()); | |
179 | |
180 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | |
181 // TODO: compute all these offsets, spans, and scales in the VS | |
182 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", w
idthHeight.fsIn()); | |
183 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", w
idthHeight.fsIn()); | |
184 fsBuilder->codeAppend("\tfloat outset = 0.5;\n"); | |
185 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0
). For rects | |
186 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a
0 .. 1 range. | |
187 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n"); | |
188 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n"); | |
189 // For rects < 1 pixel wide or tall, these scale factors are used to
cap the maximum | |
190 // value of coverage that is used. In other words it is the coverage
that is | |
191 // used in the interior of the rect after the ramp. | |
192 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\
n"); | |
193 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\
n"); | |
194 | |
195 // Compute the coverage for the rect's width | |
196 fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", | |
197 fsBuilder->fragmentPosition(), rectEdge.fsIn(
)); | |
198 fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offs
et.y * %s.z);\n", | |
199 rectEdge.fsIn(), rectEdge.fsIn()); | |
200 fsBuilder->codeAppendf( | |
201 "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0)
;\n", | |
202 widthHeight.fsIn()); | |
203 | |
204 // Compute the coverage for the rect's height and merge with the wid
th | |
205 fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", | |
206 rectEdge.fsIn()); | |
207 fsBuilder->codeAppendf( | |
208 "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.
0, 1.0);\n", | |
209 widthHeight.fsIn()); | |
210 | |
211 | |
212 fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, | |
213 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("cove
rage")).c_str()); | |
214 } | |
215 | |
216 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBu
ilder*) {} | |
217 | |
218 virtual void setData(const GrGLProgramDataManager& pdman, const GrProces
sor&) SK_OVERRIDE {} | |
219 | |
220 private: | |
221 typedef GrGLGeometryProcessor INHERITED; | |
222 }; | |
223 | |
224 | |
225 | |
226 private: | |
227 GrRectEffect() | |
228 : fInRectEdge(this->addVertexAttrib(GrShaderVar("inRectEdge", | |
229 kVec4f_GrSLType, | |
230 GrShaderVar::kAttribute_
TypeModifier))) | |
231 , fInWidthHeight(this->addVertexAttrib( | |
232 GrShaderVar("inWidthHeight", | |
233 kVec2f_GrSLType, | |
234 GrShaderVar::kAttribute_TypeModifier))) { | |
235 this->setWillReadFragmentPosition(); | |
236 } | |
237 | |
238 virtual bool onIsEqual(const GrGeometryProcessor&) const SK_OVERRIDE { retur
n true; } | |
239 | |
240 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERR
IDE { | |
241 inout->mulByUnknownAlpha(); | |
242 } | |
243 | |
244 const GrShaderVar& fInRectEdge; | |
245 const GrShaderVar& fInWidthHeight; | |
246 | |
247 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | |
248 | |
249 typedef GrGeometryProcessor INHERITED; | |
250 }; | |
251 | |
252 | |
253 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRectEffect); | |
254 | |
255 GrGeometryProcessor* GrRectEffect::TestCreate(SkRandom* random, | |
256 GrContext* context, | |
257 const GrDrawTargetCaps&, | |
258 GrTexture* textures[]) { | |
259 return GrRectEffect::Create(); | |
260 } | |
261 | |
262 /////////////////////////////////////////////////////////////////////////////// | |
263 | 18 |
264 namespace { | 19 namespace { |
265 extern const GrVertexAttrib gAARectAttribs[] = { | 20 extern const GrVertexAttrib gAARectAttribs[] = { |
266 {kVec2f_GrVertexAttribType, 0, kPosition_Gr
VertexAttribBinding}, | 21 {kVec2f_GrVertexAttribType, 0, kPosition_Gr
VertexAttribBinding}, |
267 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer
texAttribBinding}, | 22 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer
texAttribBinding}, |
268 {kFloat_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_Gr
VertexAttribBinding}, | 23 {kFloat_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_Gr
VertexAttribBinding}, |
269 }; | 24 }; |
270 | 25 |
271 // Should the coverage be multiplied into the color attrib or use a separate att
rib. | 26 // Should the coverage be multiplied into the color attrib or use a separate att
rib. |
272 enum CoverageAttribType { | 27 enum CoverageAttribType { |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 } | 296 } |
542 } | 297 } |
543 | 298 |
544 target->setIndexSourceToBuffer(indexBuffer); | 299 target->setIndexSourceToBuffer(indexBuffer); |
545 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, | 300 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, |
546 kVertsPerAAFillRect, | 301 kVertsPerAAFillRect, |
547 kIndicesPerAAFillRect); | 302 kIndicesPerAAFillRect); |
548 target->resetIndexSource(); | 303 target->resetIndexSource(); |
549 } | 304 } |
550 | 305 |
551 namespace { | |
552 | |
553 // Rotated | |
554 struct RectVertex { | |
555 SkPoint fPos; | |
556 SkPoint fCenter; | |
557 SkPoint fDir; | |
558 SkPoint fWidthHeight; | |
559 }; | |
560 | |
561 // Rotated | |
562 extern const GrVertexAttrib gAARectVertexAttribs[] = { | |
563 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing }, | |
564 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding }, | |
565 { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding } | |
566 }; | |
567 | |
568 // Axis Aligned | |
569 struct AARectVertex { | |
570 SkPoint fPos; | |
571 SkPoint fOffset; | |
572 SkPoint fWidthHeight; | |
573 }; | |
574 | |
575 // Axis Aligned | |
576 extern const GrVertexAttrib gAAAARectVertexAttribs[] = { | |
577 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing }, | |
578 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding }, | |
579 }; | |
580 | |
581 }; | |
582 | |
583 void GrAARectRenderer::shaderFillAARect(GrDrawTarget* target, | |
584 const SkRect& rect, | |
585 const SkMatrix& combinedMatrix) { | |
586 GrDrawState* drawState = target->drawState(); | |
587 | |
588 SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY()); | |
589 combinedMatrix.mapPoints(¢er, 1); | |
590 | |
591 // compute transformed (0, 1) vector | |
592 SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix:
:kMScaleY] }; | |
593 dir.normalize(); | |
594 | |
595 // compute transformed (width, 0) and (0, height) vectors | |
596 SkVector vec[2] = { | |
597 { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, | |
598 { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } | |
599 }; | |
600 | |
601 SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_Scalar
Half; | |
602 SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_Scal
arHalf; | |
603 drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVert
exAttribs), | |
604 sizeof(RectVertex)); | |
605 | |
606 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); | |
607 if (!geo.succeeded()) { | |
608 SkDebugf("Failed to get space for vertices!\n"); | |
609 return; | |
610 } | |
611 | |
612 RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices()); | |
613 | |
614 GrGeometryProcessor* gp = GrRectEffect::Create(); | |
615 drawState->setGeometryProcessor(gp)->unref(); | |
616 | |
617 for (int i = 0; i < 4; ++i) { | |
618 verts[i].fCenter = center; | |
619 verts[i].fDir = dir; | |
620 verts[i].fWidthHeight.fX = newWidth; | |
621 verts[i].fWidthHeight.fY = newHeight; | |
622 } | |
623 | |
624 SkRect devRect; | |
625 combinedMatrix.mapRect(&devRect, rect); | |
626 | |
627 SkRect devBounds = { | |
628 devRect.fLeft - SK_ScalarHalf, | |
629 devRect.fTop - SK_ScalarHalf, | |
630 devRect.fRight + SK_ScalarHalf, | |
631 devRect.fBottom + SK_ScalarHalf | |
632 }; | |
633 | |
634 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); | |
635 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); | |
636 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); | |
637 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); | |
638 | |
639 target->setIndexSourceToBuffer(fGpu->getContext()->getQuadIndexBuffer()); | |
640 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); | |
641 target->resetIndexSource(); | |
642 } | |
643 | |
644 void GrAARectRenderer::shaderFillAlignedAARect(GrDrawTarget* target, | |
645 const SkRect& rect, | |
646 const SkMatrix& combinedMatrix) { | |
647 GrDrawState* drawState = target->drawState(); | |
648 SkASSERT(combinedMatrix.rectStaysRect()); | |
649 | |
650 drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARect
VertexAttribs), | |
651 sizeof(AARectVertex)); | |
652 | |
653 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); | |
654 if (!geo.succeeded()) { | |
655 SkDebugf("Failed to get space for vertices!\n"); | |
656 return; | |
657 } | |
658 | |
659 AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices()); | |
660 | |
661 GrGeometryProcessor* gp = GrAlignedRectEffect::Create(); | |
662 drawState->setGeometryProcessor(gp)->unref(); | |
663 | |
664 SkRect devRect; | |
665 combinedMatrix.mapRect(&devRect, rect); | |
666 | |
667 SkRect devBounds = { | |
668 devRect.fLeft - SK_ScalarHalf, | |
669 devRect.fTop - SK_ScalarHalf, | |
670 devRect.fRight + SK_ScalarHalf, | |
671 devRect.fBottom + SK_ScalarHalf | |
672 }; | |
673 | |
674 SkPoint widthHeight = { | |
675 SkScalarHalf(devRect.width()) + SK_ScalarHalf, | |
676 SkScalarHalf(devRect.height()) + SK_ScalarHalf | |
677 }; | |
678 | |
679 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); | |
680 verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY); | |
681 verts[0].fWidthHeight = widthHeight; | |
682 | |
683 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); | |
684 verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY); | |
685 verts[1].fWidthHeight = widthHeight; | |
686 | |
687 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); | |
688 verts[2].fOffset = widthHeight; | |
689 verts[2].fWidthHeight = widthHeight; | |
690 | |
691 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); | |
692 verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY); | |
693 verts[3].fWidthHeight = widthHeight; | |
694 | |
695 target->setIndexSourceToBuffer(fGpu->getContext()->getQuadIndexBuffer()); | |
696 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); | |
697 target->resetIndexSource(); | |
698 } | |
699 | |
700 void GrAARectRenderer::strokeAARect(GrDrawTarget* target, | 306 void GrAARectRenderer::strokeAARect(GrDrawTarget* target, |
701 const SkRect& rect, | 307 const SkRect& rect, |
702 const SkMatrix& combinedMatrix, | 308 const SkMatrix& combinedMatrix, |
703 const SkRect& devRect, | 309 const SkRect& devRect, |
704 const SkStrokeRec& stroke) { | 310 const SkStrokeRec& stroke) { |
705 SkVector devStrokeSize; | 311 SkVector devStrokeSize; |
706 SkScalar width = stroke.getWidth(); | 312 SkScalar width = stroke.getWidth(); |
707 if (width > 0) { | 313 if (width > 0) { |
708 devStrokeSize.set(width, width); | 314 devStrokeSize.set(width, width); |
709 combinedMatrix.mapVectors(&devStrokeSize, 1); | 315 combinedMatrix.mapVectors(&devStrokeSize, 1); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 // can't call mapRect for devInside since it calls sort | 511 // can't call mapRect for devInside since it calls sort |
906 combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2)
; | 512 combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2)
; |
907 | 513 |
908 if (devInside.isEmpty()) { | 514 if (devInside.isEmpty()) { |
909 this->fillAARect(target, devOutside, SkMatrix::I(), devOutside); | 515 this->fillAARect(target, devOutside, SkMatrix::I(), devOutside); |
910 return; | 516 return; |
911 } | 517 } |
912 | 518 |
913 this->geometryStrokeAARect(target, devOutside, devOutsideAssist, devInside,
true); | 519 this->geometryStrokeAARect(target, devOutside, devOutsideAssist, devInside,
true); |
914 } | 520 } |
OLD | NEW |