OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
9 | 9 |
10 #include "GrEffect.h" | 10 #include "GrEffect.h" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 GrContext* context, | 280 GrContext* context, |
281 const GrDrawTargetCaps&, | 281 const GrDrawTargetCaps&, |
282 GrTexture* textures[]) { | 282 GrTexture* textures[]) { |
283 return EllipseEdgeEffect::Create(random->nextBool()); | 283 return EllipseEdgeEffect::Create(random->nextBool()); |
284 } | 284 } |
285 | 285 |
286 /////////////////////////////////////////////////////////////////////////////// | 286 /////////////////////////////////////////////////////////////////////////////// |
287 | 287 |
288 /** | 288 /** |
289 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned | 289 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned |
290 * ellipse, specified as an offset vector from center and outer and inner radii
in both | 290 * ellipse, specified as an offset vector from center and reciprocals of outer a
nd inner radii in |
291 * x and y directions. | 291 * both x and y directions. |
292 * | 292 * |
293 * This uses a slightly different algorithm than the EllipseEdgeEffect, above. R
ather than | 293 * This uses a slightly different algorithm than the EllipseEdgeEffect, above. R
ather than |
294 * scaling an ellipse to be a circle, it attempts to find the distance from the
offset point to the | 294 * scaling an ellipse to be a circle, it attempts to find the distance from the
offset point to the |
295 * ellipse by determining where the line through the origin and offset point wou
ld cross the | 295 * ellipse by determining where the line through the origin and offset point wou
ld cross the |
296 * ellipse, and computing the distance to that. This is slower but works better
for roundrects | 296 * ellipse, and computing the distance to that. This is slower but works better
for roundrects |
297 * because the straight edges will be more accurate. | 297 * because the straight edges will be more accurate. |
298 */ | 298 */ |
299 | 299 |
300 class AltEllipseEdgeEffect : public GrEffect { | 300 class AltEllipseEdgeEffect : public GrEffect { |
301 public: | 301 public: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_st
r()); | 350 builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_st
r()); |
351 | 351 |
352 builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &
fsRadiiName); | 352 builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &
fsRadiiName); |
353 const SkString* attr1Name = | 353 const SkString* attr1Name = |
354 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice
s()[1]); | 354 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice
s()[1]); |
355 builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str
()); | 355 builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str
()); |
356 | 356 |
357 builder->fsCodeAppend("\tfloat edgeAlpha;\n"); | 357 builder->fsCodeAppend("\tfloat edgeAlpha;\n"); |
358 // get length of offset | 358 // get length of offset |
359 builder->fsCodeAppendf("\tfloat len = length(%s.xy);\n", fsOffsetNam
e); | 359 builder->fsCodeAppendf("\tfloat len = length(%s.xy);\n", fsOffsetNam
e); |
360 builder->fsCodeAppend("\tvec2 offset;\n"); | |
361 | 360 |
362 // for outer curve | 361 // for outer curve |
363 builder->fsCodeAppendf("\toffset.xy = %s.xy*%s.yx;\n", | 362 builder->fsCodeAppendf("\tvec2 offset = %s.xy*%s.xy;\n", |
364 fsOffsetName, fsRadiiName); | 363 fsOffsetName, fsRadiiName); |
365 builder->fsCodeAppendf("\tfloat tOuter = " | 364 builder->fsCodeAppendf("\tfloat t = inversesqrt(dot(offset.xy, offse
t.xy));\n"); |
366 "%s.x*%s.y*inversesqrt(dot(offset.xy, offset.
xy));\n", | 365 builder->fsCodeAppend("\tedgeAlpha = clamp(len*t - len, 0.0, 1.0);\n
"); |
367 fsRadiiName, fsRadiiName); | |
368 builder->fsCodeAppend("\tedgeAlpha = clamp(len*tOuter - len, 0.0, 1.
0);\n"); | |
369 | 366 |
370 // for inner curve | 367 // for inner curve |
371 if (rrectEffect.isStroked()) { | 368 if (rrectEffect.isStroked()) { |
372 builder->fsCodeAppendf("\toffset.xy = %s.xy*%s.wz;\n", | 369 builder->fsCodeAppendf("\toffset = %s.xy*%s.zw;\n", |
373 fsOffsetName, fsRadiiName); | 370 fsOffsetName, fsRadiiName); |
374 builder->fsCodeAppendf("\tfloat tInner = " | 371 builder->fsCodeAppendf("\tt = inversesqrt(dot(offset.xy, offset.
xy));\n"); |
375 "%s.z*%s.w*inversesqrt(dot(offset.xy, off
set.xy));\n", | 372 builder->fsCodeAppend("\tedgeAlpha *= clamp(len - len*t, 0.0, 1.
0);\n"); |
376 fsRadiiName, fsRadiiName); | |
377 builder->fsCodeAppend("\tedgeAlpha *= clamp(len - len*tInner, 0.
0, 1.0);\n"); | |
378 } | 373 } |
379 | 374 |
380 SkString modulate; | 375 SkString modulate; |
381 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); | 376 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); |
382 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()
); | 377 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()
); |
383 } | 378 } |
384 | 379 |
385 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG
LCaps&) { | 380 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG
LCaps&) { |
386 const AltEllipseEdgeEffect& rrectEffect = drawEffect.castEffect<AltE
llipseEdgeEffect>(); | 381 const AltEllipseEdgeEffect& rrectEffect = drawEffect.castEffect<AltE
llipseEdgeEffect>(); |
387 | 382 |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 bounds.fBottom - yOuterRadius, | 947 bounds.fBottom - yOuterRadius, |
953 bounds.fBottom | 948 bounds.fBottom |
954 }; | 949 }; |
955 SkScalar yOuterOffsets[4] = { | 950 SkScalar yOuterOffsets[4] = { |
956 -yOuterRadius, | 951 -yOuterRadius, |
957 SK_ScalarNearlyZero, // we're using inversesqrt() in the shader, so
can't be exactly 0 | 952 SK_ScalarNearlyZero, // we're using inversesqrt() in the shader, so
can't be exactly 0 |
958 SK_ScalarNearlyZero, | 953 SK_ScalarNearlyZero, |
959 yOuterRadius | 954 yOuterRadius |
960 }; | 955 }; |
961 | 956 |
| 957 SkScalar recipOuterX = SK_Scalar1/xOuterRadius; |
| 958 SkScalar recipOuterY = SK_Scalar1/yOuterRadius; |
| 959 SkScalar recipInnerX = SK_Scalar1/xInnerRadius; |
| 960 SkScalar recipInnerY = SK_Scalar1/yInnerRadius; |
| 961 |
962 for (int i = 0; i < 4; ++i) { | 962 for (int i = 0; i < 4; ++i) { |
963 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); | 963 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); |
964 verts->fOffset = SkPoint::Make(-xOuterRadius, yOuterOffsets[i]); | 964 verts->fOffset = SkPoint::Make(-xOuterRadius, yOuterOffsets[i]); |
965 verts->fOuterRadii = SkPoint::Make(xOuterRadius, yOuterRadius); | 965 verts->fOuterRadii = SkPoint::Make(recipOuterX, recipOuterY); |
966 verts->fInnerRadii = SkPoint::Make(xInnerRadius, yInnerRadius); | 966 verts->fInnerRadii = SkPoint::Make(recipInnerX, recipInnerY); |
967 verts++; | 967 verts++; |
968 | 968 |
969 verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i])
; | 969 verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i])
; |
970 verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]
); | 970 verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]
); |
971 verts->fOuterRadii = SkPoint::Make(xOuterRadius, yOuterRadius); | 971 verts->fOuterRadii = SkPoint::Make(recipOuterX, recipOuterY); |
972 verts->fInnerRadii = SkPoint::Make(xInnerRadius, yInnerRadius); | 972 verts->fInnerRadii = SkPoint::Make(recipInnerX, recipInnerY); |
973 verts++; | 973 verts++; |
974 | 974 |
975 verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]
); | 975 verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]
); |
976 verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]
); | 976 verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]
); |
977 verts->fOuterRadii = SkPoint::Make(xOuterRadius, yOuterRadius); | 977 verts->fOuterRadii = SkPoint::Make(recipOuterX, recipOuterY); |
978 verts->fInnerRadii = SkPoint::Make(xInnerRadius, yInnerRadius); | 978 verts->fInnerRadii = SkPoint::Make(recipInnerX, recipInnerY); |
979 verts++; | 979 verts++; |
980 | 980 |
981 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); | 981 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); |
982 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); | 982 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); |
983 verts->fOuterRadii = SkPoint::Make(xOuterRadius, yOuterRadius); | 983 verts->fOuterRadii = SkPoint::Make(recipOuterX, recipOuterY); |
984 verts->fInnerRadii = SkPoint::Make(xInnerRadius, yInnerRadius); | 984 verts->fInnerRadii = SkPoint::Make(recipInnerX, recipInnerY); |
985 verts++; | 985 verts++; |
986 } | 986 } |
987 | 987 |
988 // drop out the middle quad if we're stroked | 988 // drop out the middle quad if we're stroked |
989 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO
UNT(gRRectIndices); | 989 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO
UNT(gRRectIndices); |
990 target->setIndexSourceToBuffer(indexBuffer); | 990 target->setIndexSourceToBuffer(indexBuffer); |
991 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou
nds); | 991 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou
nds); |
992 } | 992 } |
993 | 993 |
994 return true; | 994 return true; |
995 } | 995 } |
OLD | NEW |