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 "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrBatchTarget.h" | 11 #include "GrBatchTarget.h" |
12 #include "GrBatchTest.h" | |
12 #include "GrBufferAllocPool.h" | 13 #include "GrBufferAllocPool.h" |
13 #include "GrDrawTarget.h" | 14 #include "GrDrawTarget.h" |
14 #include "GrGeometryProcessor.h" | 15 #include "GrGeometryProcessor.h" |
15 #include "GrGpu.h" | 16 #include "GrGpu.h" |
16 #include "GrInvariantOutput.h" | 17 #include "GrInvariantOutput.h" |
17 #include "GrPipelineBuilder.h" | 18 #include "GrPipelineBuilder.h" |
18 #include "GrProcessor.h" | 19 #include "GrProcessor.h" |
19 #include "GrVertexBuffer.h" | 20 #include "GrVertexBuffer.h" |
20 #include "SkRRect.h" | 21 #include "SkRRect.h" |
21 #include "SkStrokeRec.h" | 22 #include "SkStrokeRec.h" |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 bool fCoverageIgnored; | 872 bool fCoverageIgnored; |
872 }; | 873 }; |
873 | 874 |
874 static const int kVertsPerCircle = 4; | 875 static const int kVertsPerCircle = 4; |
875 static const int kIndicesPerCircle = 6; | 876 static const int kIndicesPerCircle = 6; |
876 | 877 |
877 BatchTracker fBatch; | 878 BatchTracker fBatch; |
878 SkSTArray<1, Geometry, true> fGeoData; | 879 SkSTArray<1, Geometry, true> fGeoData; |
879 }; | 880 }; |
880 | 881 |
881 void GrOvalRenderer::drawCircle(GrDrawTarget* target, | 882 static GrBatch* create_circle_batch(GrColor color, |
882 GrPipelineBuilder* pipelineBuilder, | 883 const SkMatrix& viewMatrix, |
883 GrColor color, | 884 bool useCoverageAA, |
884 const SkMatrix& viewMatrix, | 885 const SkRect& circle, |
885 bool useCoverageAA, | 886 const SkStrokeRec& stroke, |
886 const SkRect& circle, | 887 SkRect* bounds) { |
887 const SkStrokeRec& stroke) { | |
888 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 888 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
889 viewMatrix.mapPoints(¢er, 1); | 889 viewMatrix.mapPoints(¢er, 1); |
890 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); | 890 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); |
891 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); | 891 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); |
892 | 892 |
893 SkStrokeRec::Style style = stroke.getStyle(); | 893 SkStrokeRec::Style style = stroke.getStyle(); |
894 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 894 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
895 SkStrokeRec::kHairline_Style == style; | 895 SkStrokeRec::kHairline_Style == style; |
896 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 896 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
897 | 897 |
(...skipping 12 matching lines...) Expand all Loading... | |
910 innerRadius = radius - halfWidth; | 910 innerRadius = radius - halfWidth; |
911 } | 911 } |
912 } | 912 } |
913 | 913 |
914 // The radii are outset for two reasons. First, it allows the shader to simp ly perform simpler | 914 // The radii are outset for two reasons. First, it allows the shader to simp ly perform simpler |
915 // computation because the computed alpha is zero, rather than 50%, at the r adius. | 915 // computation because the computed alpha is zero, rather than 50%, at the r adius. |
916 // Second, the outer radius is used to compute the verts of the bounding box that is rendered | 916 // Second, the outer radius is used to compute the verts of the bounding box that is rendered |
917 // and the outset ensures the box will cover all partially covered by the ci rcle. | 917 // and the outset ensures the box will cover all partially covered by the ci rcle. |
918 outerRadius += SK_ScalarHalf; | 918 outerRadius += SK_ScalarHalf; |
919 innerRadius -= SK_ScalarHalf; | 919 innerRadius -= SK_ScalarHalf; |
920 | 920 |
robertphillips
2015/04/30 14:07:32
bounds->setLTRB(... ?
also, just 2 lines ?
| |
921 SkRect bounds = SkRect::MakeLTRB( | 921 *bounds = SkRect::MakeLTRB( |
922 center.fX - outerRadius, | 922 center.fX - outerRadius, |
923 center.fY - outerRadius, | 923 center.fY - outerRadius, |
924 center.fX + outerRadius, | 924 center.fX + outerRadius, |
925 center.fY + outerRadius | 925 center.fY + outerRadius |
926 ); | 926 ); |
927 | 927 |
928 CircleBatch::Geometry geometry; | 928 CircleBatch::Geometry geometry; |
929 geometry.fViewMatrix = viewMatrix; | 929 geometry.fViewMatrix = viewMatrix; |
930 geometry.fColor = color; | 930 geometry.fColor = color; |
931 geometry.fInnerRadius = innerRadius; | 931 geometry.fInnerRadius = innerRadius; |
932 geometry.fOuterRadius = outerRadius; | 932 geometry.fOuterRadius = outerRadius; |
933 geometry.fStroke = isStrokeOnly && innerRadius > 0; | 933 geometry.fStroke = isStrokeOnly && innerRadius > 0; |
934 geometry.fDevBounds = bounds; | 934 geometry.fDevBounds = *bounds; |
935 | 935 |
936 SkAutoTUnref<GrBatch> batch(CircleBatch::Create(geometry)); | 936 return CircleBatch::Create(geometry); |
937 } | |
938 | |
939 void GrOvalRenderer::drawCircle(GrDrawTarget* target, | |
940 GrPipelineBuilder* pipelineBuilder, | |
941 GrColor color, | |
942 const SkMatrix& viewMatrix, | |
943 bool useCoverageAA, | |
944 const SkRect& circle, | |
945 const SkStrokeRec& stroke) { | |
946 SkRect bounds; | |
947 SkAutoTUnref<GrBatch> batch(create_circle_batch(color, viewMatrix, useCovera geAA, circle, | |
948 stroke, &bounds)); | |
937 target->drawBatch(pipelineBuilder, batch, &bounds); | 949 target->drawBatch(pipelineBuilder, batch, &bounds); |
938 } | 950 } |
939 | 951 |
940 /////////////////////////////////////////////////////////////////////////////// | 952 /////////////////////////////////////////////////////////////////////////////// |
941 | 953 |
942 class EllipseBatch : public GrBatch { | 954 class EllipseBatch : public GrBatch { |
943 public: | 955 public: |
944 struct Geometry { | 956 struct Geometry { |
945 GrColor fColor; | 957 GrColor fColor; |
946 SkMatrix fViewMatrix; | 958 SkMatrix fViewMatrix; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 bool fCoverageIgnored; | 1143 bool fCoverageIgnored; |
1132 }; | 1144 }; |
1133 | 1145 |
1134 static const int kVertsPerEllipse = 4; | 1146 static const int kVertsPerEllipse = 4; |
1135 static const int kIndicesPerEllipse = 6; | 1147 static const int kIndicesPerEllipse = 6; |
1136 | 1148 |
1137 BatchTracker fBatch; | 1149 BatchTracker fBatch; |
1138 SkSTArray<1, Geometry, true> fGeoData; | 1150 SkSTArray<1, Geometry, true> fGeoData; |
1139 }; | 1151 }; |
1140 | 1152 |
1141 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, | 1153 static GrBatch* create_ellipse_batch(GrColor color, |
1142 GrPipelineBuilder* pipelineBuilder, | 1154 const SkMatrix& viewMatrix, |
1143 GrColor color, | 1155 bool useCoverageAA, |
1144 const SkMatrix& viewMatrix, | 1156 const SkRect& ellipse, |
1145 bool useCoverageAA, | 1157 const SkStrokeRec& stroke, |
1146 const SkRect& ellipse, | 1158 SkRect* bounds) { |
1147 const SkStrokeRec& stroke) { | |
1148 #ifdef SK_DEBUG | |
1149 { | |
1150 // we should have checked for this previously | |
1151 bool isAxisAlignedEllipse = viewMatrix.rectStaysRect(); | |
1152 SkASSERT(useCoverageAA && isAxisAlignedEllipse); | |
1153 } | |
1154 #endif | |
1155 | |
1156 // do any matrix crunching before we reset the draw state for device coords | 1159 // do any matrix crunching before we reset the draw state for device coords |
1157 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 1160 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
1158 viewMatrix.mapPoints(¢er, 1); | 1161 viewMatrix.mapPoints(¢er, 1); |
1159 SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); | 1162 SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); |
1160 SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); | 1163 SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); |
1161 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*ellipseXRadius + | 1164 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*ellipseXRadius + |
1162 viewMatrix[SkMatrix::kMSkewY]*ellipseYRadius) ; | 1165 viewMatrix[SkMatrix::kMSkewY]*ellipseYRadius) ; |
1163 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*ellipseXRadius + | 1166 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*ellipseXRadius + |
1164 viewMatrix[SkMatrix::kMScaleY]*ellipseYRadius ); | 1167 viewMatrix[SkMatrix::kMScaleY]*ellipseYRadius ); |
1165 | 1168 |
(...skipping 15 matching lines...) Expand all Loading... | |
1181 if (hasStroke) { | 1184 if (hasStroke) { |
1182 if (SkScalarNearlyZero(scaledStroke.length())) { | 1185 if (SkScalarNearlyZero(scaledStroke.length())) { |
1183 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1186 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
1184 } else { | 1187 } else { |
1185 scaledStroke.scale(SK_ScalarHalf); | 1188 scaledStroke.scale(SK_ScalarHalf); |
1186 } | 1189 } |
1187 | 1190 |
1188 // we only handle thick strokes for near-circular ellipses | 1191 // we only handle thick strokes for near-circular ellipses |
1189 if (scaledStroke.length() > SK_ScalarHalf && | 1192 if (scaledStroke.length() > SK_ScalarHalf && |
1190 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { | 1193 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { |
1191 return false; | 1194 return NULL; |
1192 } | 1195 } |
1193 | 1196 |
1194 // we don't handle it if curvature of the stroke is less than curvature of the ellipse | 1197 // we don't handle it if curvature of the stroke is less than curvature of the ellipse |
1195 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY )*xRadius || | 1198 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY )*xRadius || |
1196 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX )*yRadius) { | 1199 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX )*yRadius) { |
1197 return false; | 1200 return NULL; |
1198 } | 1201 } |
1199 | 1202 |
1200 // this is legit only if scale & translation (which should be the case a t the moment) | 1203 // this is legit only if scale & translation (which should be the case a t the moment) |
1201 if (isStrokeOnly) { | 1204 if (isStrokeOnly) { |
1202 innerXRadius = xRadius - scaledStroke.fX; | 1205 innerXRadius = xRadius - scaledStroke.fX; |
1203 innerYRadius = yRadius - scaledStroke.fY; | 1206 innerYRadius = yRadius - scaledStroke.fY; |
1204 } | 1207 } |
1205 | 1208 |
1206 xRadius += scaledStroke.fX; | 1209 xRadius += scaledStroke.fX; |
1207 yRadius += scaledStroke.fY; | 1210 yRadius += scaledStroke.fY; |
1208 } | 1211 } |
1209 | 1212 |
1210 // We've extended the outer x radius out half a pixel to antialias. | 1213 // We've extended the outer x radius out half a pixel to antialias. |
1211 // This will also expand the rect so all the pixels will be captured. | 1214 // This will also expand the rect so all the pixels will be captured. |
1212 // TODO: Consider if we should use sqrt(2)/2 instead | 1215 // TODO: Consider if we should use sqrt(2)/2 instead |
1213 xRadius += SK_ScalarHalf; | 1216 xRadius += SK_ScalarHalf; |
1214 yRadius += SK_ScalarHalf; | 1217 yRadius += SK_ScalarHalf; |
1215 | 1218 |
robertphillips
2015/04/30 14:07:32
same
| |
1216 SkRect bounds = SkRect::MakeLTRB( | 1219 *bounds = SkRect::MakeLTRB( |
1217 center.fX - xRadius, | 1220 center.fX - xRadius, |
1218 center.fY - yRadius, | 1221 center.fY - yRadius, |
1219 center.fX + xRadius, | 1222 center.fX + xRadius, |
1220 center.fY + yRadius | 1223 center.fY + yRadius |
1221 ); | 1224 ); |
1222 | 1225 |
1223 EllipseBatch::Geometry geometry; | 1226 EllipseBatch::Geometry geometry; |
1224 geometry.fViewMatrix = viewMatrix; | 1227 geometry.fViewMatrix = viewMatrix; |
1225 geometry.fColor = color; | 1228 geometry.fColor = color; |
1226 geometry.fXRadius = xRadius; | 1229 geometry.fXRadius = xRadius; |
1227 geometry.fYRadius = yRadius; | 1230 geometry.fYRadius = yRadius; |
1228 geometry.fInnerXRadius = innerXRadius; | 1231 geometry.fInnerXRadius = innerXRadius; |
1229 geometry.fInnerYRadius = innerYRadius; | 1232 geometry.fInnerYRadius = innerYRadius; |
1230 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; | 1233 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; |
1231 geometry.fDevBounds = bounds; | 1234 geometry.fDevBounds = *bounds; |
1232 | 1235 |
1233 SkAutoTUnref<GrBatch> batch(EllipseBatch::Create(geometry)); | 1236 return EllipseBatch::Create(geometry); |
1237 } | |
1238 | |
1239 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, | |
1240 GrPipelineBuilder* pipelineBuilder, | |
1241 GrColor color, | |
1242 const SkMatrix& viewMatrix, | |
1243 bool useCoverageAA, | |
1244 const SkRect& ellipse, | |
1245 const SkStrokeRec& stroke) { | |
robertphillips
2015/04/30 14:07:32
Should this assert go in create_ellipse_batch ?
| |
1246 #ifdef SK_DEBUG | |
1247 { | |
1248 // we should have checked for this previously | |
1249 bool isAxisAlignedEllipse = viewMatrix.rectStaysRect(); | |
1250 SkASSERT(useCoverageAA && isAxisAlignedEllipse); | |
1251 } | |
1252 #endif | |
1253 | |
1254 SkRect bounds; | |
1255 SkAutoTUnref<GrBatch> batch(create_ellipse_batch(color, viewMatrix, useCover ageAA, ellipse, | |
1256 stroke, &bounds)); | |
1257 if (!batch) { | |
1258 return false; | |
1259 } | |
1260 | |
1234 target->drawBatch(pipelineBuilder, batch, &bounds); | 1261 target->drawBatch(pipelineBuilder, batch, &bounds); |
1235 | |
1236 return true; | 1262 return true; |
1237 } | 1263 } |
1238 | 1264 |
1239 //////////////////////////////////////////////////////////////////////////////// ///////////////// | 1265 //////////////////////////////////////////////////////////////////////////////// ///////////////// |
1240 | 1266 |
1241 class DIEllipseBatch : public GrBatch { | 1267 class DIEllipseBatch : public GrBatch { |
1242 public: | 1268 public: |
1243 struct Geometry { | 1269 struct Geometry { |
1244 GrColor fColor; | 1270 GrColor fColor; |
1245 SkMatrix fViewMatrix; | 1271 SkMatrix fViewMatrix; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1423 bool fCoverageIgnored; | 1449 bool fCoverageIgnored; |
1424 }; | 1450 }; |
1425 | 1451 |
1426 static const int kVertsPerEllipse = 4; | 1452 static const int kVertsPerEllipse = 4; |
1427 static const int kIndicesPerEllipse = 6; | 1453 static const int kIndicesPerEllipse = 6; |
1428 | 1454 |
1429 BatchTracker fBatch; | 1455 BatchTracker fBatch; |
1430 SkSTArray<1, Geometry, true> fGeoData; | 1456 SkSTArray<1, Geometry, true> fGeoData; |
1431 }; | 1457 }; |
1432 | 1458 |
1433 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, | 1459 static GrBatch* create_diellipse_batch(GrColor color, |
1434 GrPipelineBuilder* pipelineBuilder, | 1460 const SkMatrix& viewMatrix, |
1435 GrColor color, | 1461 bool useCoverageAA, |
1436 const SkMatrix& viewMatrix, | 1462 const SkRect& ellipse, |
1437 bool useCoverageAA, | 1463 const SkStrokeRec& stroke, |
1438 const SkRect& ellipse, | 1464 SkRect* bounds) { |
1439 const SkStrokeRec& stroke) { | |
1440 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 1465 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
1441 SkScalar xRadius = SkScalarHalf(ellipse.width()); | 1466 SkScalar xRadius = SkScalarHalf(ellipse.width()); |
1442 SkScalar yRadius = SkScalarHalf(ellipse.height()); | 1467 SkScalar yRadius = SkScalarHalf(ellipse.height()); |
1443 | 1468 |
1444 SkStrokeRec::Style style = stroke.getStyle(); | 1469 SkStrokeRec::Style style = stroke.getStyle(); |
1445 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? | 1470 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? |
1446 DIEllipseEdgeEffect::kStroke : | 1471 DIEllipseEdgeEffect::kStroke : |
1447 (SkStrokeRec::kHairline_Style == style) ? | 1472 (SkStrokeRec::kHairline_Style == style) ? |
1448 DIEllipseEdgeEffect::kHairline : DIEllipseEd geEffect::kFill; | 1473 DIEllipseEdgeEffect::kHairline : DIEllipseEd geEffect::kFill; |
1449 | 1474 |
1450 SkScalar innerXRadius = 0; | 1475 SkScalar innerXRadius = 0; |
1451 SkScalar innerYRadius = 0; | 1476 SkScalar innerYRadius = 0; |
1452 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) { | 1477 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) { |
1453 SkScalar strokeWidth = stroke.getWidth(); | 1478 SkScalar strokeWidth = stroke.getWidth(); |
1454 | 1479 |
1455 if (SkScalarNearlyZero(strokeWidth)) { | 1480 if (SkScalarNearlyZero(strokeWidth)) { |
1456 strokeWidth = SK_ScalarHalf; | 1481 strokeWidth = SK_ScalarHalf; |
1457 } else { | 1482 } else { |
1458 strokeWidth *= SK_ScalarHalf; | 1483 strokeWidth *= SK_ScalarHalf; |
1459 } | 1484 } |
1460 | 1485 |
1461 // we only handle thick strokes for near-circular ellipses | 1486 // we only handle thick strokes for near-circular ellipses |
1462 if (strokeWidth > SK_ScalarHalf && | 1487 if (strokeWidth > SK_ScalarHalf && |
1463 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { | 1488 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { |
1464 return false; | 1489 return NULL; |
1465 } | 1490 } |
1466 | 1491 |
1467 // we don't handle it if curvature of the stroke is less than curvature of the ellipse | 1492 // we don't handle it if curvature of the stroke is less than curvature of the ellipse |
1468 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || | 1493 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || |
1469 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { | 1494 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { |
1470 return false; | 1495 return NULL; |
1471 } | 1496 } |
1472 | 1497 |
1473 // set inner radius (if needed) | 1498 // set inner radius (if needed) |
1474 if (SkStrokeRec::kStroke_Style == style) { | 1499 if (SkStrokeRec::kStroke_Style == style) { |
1475 innerXRadius = xRadius - strokeWidth; | 1500 innerXRadius = xRadius - strokeWidth; |
1476 innerYRadius = yRadius - strokeWidth; | 1501 innerYRadius = yRadius - strokeWidth; |
1477 } | 1502 } |
1478 | 1503 |
1479 xRadius += strokeWidth; | 1504 xRadius += strokeWidth; |
1480 yRadius += strokeWidth; | 1505 yRadius += strokeWidth; |
1481 } | 1506 } |
1482 if (DIEllipseEdgeEffect::kStroke == mode) { | 1507 if (DIEllipseEdgeEffect::kStroke == mode) { |
1483 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt roke : | 1508 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt roke : |
1484 DIEllipseEdgeEffect::kFi ll; | 1509 DIEllipseEdgeEffect::kFi ll; |
1485 } | 1510 } |
1486 | 1511 |
1487 // This expands the outer rect so that after CTM we end up with a half-pixel border | 1512 // This expands the outer rect so that after CTM we end up with a half-pixel border |
1488 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; | 1513 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; |
1489 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; | 1514 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; |
1490 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; | 1515 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; |
1491 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; | 1516 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; |
1492 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); | 1517 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); |
1493 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); | 1518 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); |
1494 | 1519 |
robertphillips
2015/04/30 14:07:32
same
| |
1495 SkRect bounds = SkRect::MakeLTRB( | 1520 *bounds = SkRect::MakeLTRB( |
1496 center.fX - xRadius - geoDx, | 1521 center.fX - xRadius - geoDx, |
1497 center.fY - yRadius - geoDy, | 1522 center.fY - yRadius - geoDy, |
1498 center.fX + xRadius + geoDx, | 1523 center.fX + xRadius + geoDx, |
1499 center.fY + yRadius + geoDy | 1524 center.fY + yRadius + geoDy |
1500 ); | 1525 ); |
1501 | 1526 |
1502 DIEllipseBatch::Geometry geometry; | 1527 DIEllipseBatch::Geometry geometry; |
1503 geometry.fViewMatrix = viewMatrix; | 1528 geometry.fViewMatrix = viewMatrix; |
1504 geometry.fColor = color; | 1529 geometry.fColor = color; |
1505 geometry.fXRadius = xRadius; | 1530 geometry.fXRadius = xRadius; |
1506 geometry.fYRadius = yRadius; | 1531 geometry.fYRadius = yRadius; |
1507 geometry.fInnerXRadius = innerXRadius; | 1532 geometry.fInnerXRadius = innerXRadius; |
1508 geometry.fInnerYRadius = innerYRadius; | 1533 geometry.fInnerYRadius = innerYRadius; |
1509 geometry.fGeoDx = geoDx; | 1534 geometry.fGeoDx = geoDx; |
1510 geometry.fGeoDy = geoDy; | 1535 geometry.fGeoDy = geoDy; |
1511 geometry.fMode = mode; | 1536 geometry.fMode = mode; |
1512 geometry.fBounds = bounds; | 1537 geometry.fBounds = *bounds; |
1513 | 1538 |
1514 viewMatrix.mapRect(&bounds); | 1539 viewMatrix.mapRect(bounds); |
1540 return DIEllipseBatch::Create(geometry); | |
1541 } | |
1515 | 1542 |
1516 SkAutoTUnref<GrBatch> batch(DIEllipseBatch::Create(geometry)); | 1543 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, |
1544 GrPipelineBuilder* pipelineBuilder, | |
1545 GrColor color, | |
1546 const SkMatrix& viewMatrix, | |
1547 bool useCoverageAA, | |
1548 const SkRect& ellipse, | |
1549 const SkStrokeRec& stroke) { | |
1550 SkRect bounds; | |
1551 SkAutoTUnref<GrBatch> batch(create_diellipse_batch(color, viewMatrix, useCov erageAA, ellipse, | |
1552 stroke, &bounds)); | |
1553 if (!batch) { | |
1554 return false; | |
1555 } | |
1517 target->drawBatch(pipelineBuilder, batch, &bounds); | 1556 target->drawBatch(pipelineBuilder, batch, &bounds); |
1518 | |
1519 return true; | 1557 return true; |
1520 } | 1558 } |
1521 | 1559 |
1522 /////////////////////////////////////////////////////////////////////////////// | 1560 /////////////////////////////////////////////////////////////////////////////// |
1523 | 1561 |
1524 static const uint16_t gRRectIndices[] = { | 1562 static const uint16_t gRRectIndices[] = { |
1525 // corners | 1563 // corners |
1526 0, 1, 5, 0, 5, 4, | 1564 0, 1, 5, 0, 5, 4, |
1527 2, 3, 7, 2, 7, 6, | 1565 2, 3, 7, 2, 7, 6, |
1528 8, 9, 13, 8, 13, 12, | 1566 8, 9, 13, 8, 13, 12, |
1529 10, 11, 15, 10, 15, 14, | 1567 10, 11, 15, 10, 15, 14, |
1530 | 1568 |
1531 // edges | 1569 // edges |
1532 1, 2, 6, 1, 6, 5, | 1570 1, 2, 6, 1, 6, 5, |
1533 4, 5, 9, 4, 9, 8, | 1571 4, 5, 9, 4, 9, 8, |
1534 6, 7, 11, 6, 11, 10, | 1572 6, 7, 11, 6, 11, 10, |
1535 9, 10, 14, 9, 14, 13, | 1573 9, 10, 14, 9, 14, 13, |
1536 | 1574 |
1537 // center | 1575 // center |
1538 // we place this at the end so that we can ignore these indices when renderi ng stroke-only | 1576 // we place this at the end so that we can ignore these indices when renderi ng stroke-only |
1539 5, 6, 10, 5, 10, 9 | 1577 5, 6, 10, 5, 10, 9 |
1540 }; | 1578 }; |
1541 | 1579 |
1542 static const int kIndicesPerStrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6; | 1580 static const int kIndicesPerStrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6; |
1543 static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); | 1581 static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); |
1544 static const int kVertsPerRRect = 16; | 1582 static const int kVertsPerRRect = 16; |
1545 static const int kNumRRectsInIndexBuffer = 256; | 1583 static const int kNumRRectsInIndexBuffer = 256; |
1546 | 1584 |
1547 GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(bool isStrokeOnly) { | |
1548 if (isStrokeOnly) { | |
1549 if (NULL == fStrokeRRectIndexBuffer) { | |
1550 fStrokeRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectInd ices, | |
1551 kIndicesP erStrokeRRect, | |
1552 kNumRRect sInIndexBuffer, | |
1553 kVertsPer RRect); | |
1554 } | |
1555 return fStrokeRRectIndexBuffer; | |
1556 } else { | |
1557 if (NULL == fRRectIndexBuffer) { | |
1558 fRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectIndices, | |
1559 kIndicesPerRRec t, | |
1560 kNumRRectsInInd exBuffer, | |
1561 kVertsPerRRect) ; | |
1562 } | |
1563 return fRRectIndexBuffer; | |
1564 } | |
1565 } | |
1566 | |
1567 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, | 1585 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, |
1568 GrPipelineBuilder* pipelineBuilder, | 1586 GrPipelineBuilder* pipelineBuilder, |
1569 GrColor color, | 1587 GrColor color, |
1570 const SkMatrix& viewMatrix, | 1588 const SkMatrix& viewMatrix, |
1571 bool useAA, | 1589 bool useAA, |
1572 const SkRRect& origOuter, | 1590 const SkRRect& origOuter, |
1573 const SkRRect& origInner) { | 1591 const SkRRect& origInner) { |
1574 bool applyAA = useAA && | 1592 bool applyAA = useAA && |
1575 !pipelineBuilder->getRenderTarget()->isMultisampled(); | 1593 !pipelineBuilder->getRenderTarget()->isMultisampled(); |
1576 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; | 1594 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2050 bool fUsesLocalCoords; | 2068 bool fUsesLocalCoords; |
2051 bool fColorIgnored; | 2069 bool fColorIgnored; |
2052 bool fCoverageIgnored; | 2070 bool fCoverageIgnored; |
2053 }; | 2071 }; |
2054 | 2072 |
2055 BatchTracker fBatch; | 2073 BatchTracker fBatch; |
2056 SkSTArray<1, Geometry, true> fGeoData; | 2074 SkSTArray<1, Geometry, true> fGeoData; |
2057 const GrIndexBuffer* fIndexBuffer; | 2075 const GrIndexBuffer* fIndexBuffer; |
2058 }; | 2076 }; |
2059 | 2077 |
2060 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, | 2078 static GrIndexBuffer* create_rrect_indexbuffer(GrIndexBuffer** strokeRRectIndexB uffer, |
2061 GrPipelineBuilder* pipelineBuilder, | 2079 GrIndexBuffer** rrectIndexBuffer, |
2062 GrColor color, | 2080 bool isStrokeOnly, |
2063 const SkMatrix& viewMatrix, | 2081 GrGpu* gpu) { |
2064 bool useAA, | 2082 if (isStrokeOnly) { |
2065 const SkRRect& rrect, | 2083 if (NULL == *strokeRRectIndexBuffer) { |
2066 const SkStrokeRec& stroke) { | 2084 *strokeRRectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndi ces, |
2067 if (rrect.isOval()) { | 2085 kIndicesPe rStrokeRRect, |
2068 return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(), | 2086 kNumRRects InIndexBuffer, |
2069 stroke); | 2087 kVertsPerR Rect); |
2088 } | |
2089 return *strokeRRectIndexBuffer; | |
2090 } else { | |
2091 if (NULL == *rrectIndexBuffer) { | |
2092 *rrectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices, | |
2093 kIndicesPerRRect , | |
2094 kNumRRectsInInde xBuffer, | |
2095 kVertsPerRRect); | |
2096 } | |
2097 return *rrectIndexBuffer; | |
2070 } | 2098 } |
2099 } | |
2071 | 2100 |
2072 bool useCoverageAA = useAA && | 2101 static GrBatch* create_rrect_batch(GrColor color, |
2073 !pipelineBuilder->getRenderTarget()->isMultisampled(); | 2102 const SkMatrix& viewMatrix, |
2074 | 2103 const SkRRect& rrect, |
2075 // only anti-aliased rrects for now | 2104 const SkStrokeRec& stroke, |
2076 if (!useCoverageAA) { | 2105 SkRect* bounds, |
2077 return false; | 2106 GrIndexBuffer** strokeRRectIndexBuffer, |
2078 } | 2107 GrIndexBuffer** rrectIndexBuffer, |
2079 | 2108 GrGpu* gpu) { |
robertphillips
2015/04/30 14:07:32
SkASSERT(viewMatrix.rectStaysRect());
SkASSERT(rre
| |
2080 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { | |
2081 return false; | |
2082 } | |
2083 | |
2084 // do any matrix crunching before we reset the draw state for device coords | 2109 // do any matrix crunching before we reset the draw state for device coords |
2085 const SkRect& rrectBounds = rrect.getBounds(); | 2110 const SkRect& rrectBounds = rrect.getBounds(); |
2086 SkRect bounds; | 2111 viewMatrix.mapRect(bounds, rrectBounds); |
2087 viewMatrix.mapRect(&bounds, rrectBounds); | |
2088 | 2112 |
2089 SkVector radii = rrect.getSimpleRadii(); | 2113 SkVector radii = rrect.getSimpleRadii(); |
2090 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + | 2114 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + |
2091 viewMatrix[SkMatrix::kMSkewY]*radii.fY); | 2115 viewMatrix[SkMatrix::kMSkewY]*radii.fY); |
2092 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*radii.fX + | 2116 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*radii.fX + |
2093 viewMatrix[SkMatrix::kMScaleY]*radii.fY); | 2117 viewMatrix[SkMatrix::kMScaleY]*radii.fY); |
2094 | 2118 |
2095 SkStrokeRec::Style style = stroke.getStyle(); | 2119 SkStrokeRec::Style style = stroke.getStyle(); |
2096 | 2120 |
2097 // do (potentially) anisotropic mapping of stroke | 2121 // do (potentially) anisotropic mapping of stroke |
2098 SkVector scaledStroke; | 2122 SkVector scaledStroke; |
2099 SkScalar strokeWidth = stroke.getWidth(); | 2123 SkScalar strokeWidth = stroke.getWidth(); |
2100 | 2124 |
2101 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 2125 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
2102 SkStrokeRec::kHairline_Style == style; | 2126 SkStrokeRec::kHairline_Style == style; |
2103 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 2127 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
2104 | 2128 |
2105 if (hasStroke) { | 2129 if (hasStroke) { |
2106 if (SkStrokeRec::kHairline_Style == style) { | 2130 if (SkStrokeRec::kHairline_Style == style) { |
2107 scaledStroke.set(1, 1); | 2131 scaledStroke.set(1, 1); |
2108 } else { | 2132 } else { |
2109 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc aleX] + | 2133 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc aleX] + |
2110 viewMatrix[SkMatrix::kMSk ewY])); | 2134 viewMatrix[SkMatrix::kMSk ewY])); |
2111 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk ewX] + | 2135 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk ewX] + |
2112 viewMatrix[SkMatrix::kMSc aleY])); | 2136 viewMatrix[SkMatrix::kMSc aleY])); |
2113 } | 2137 } |
2114 | 2138 |
2115 // if half of strokewidth is greater than radius, we don't handle that r ight now | 2139 // if half of strokewidth is greater than radius, we don't handle that r ight now |
2116 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok e.fY > yRadius) { | 2140 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok e.fY > yRadius) { |
2117 return false; | 2141 return NULL; |
2118 } | 2142 } |
2119 } | 2143 } |
2120 | 2144 |
2121 // The way the effect interpolates the offset-to-ellipse/circle-center attri bute only works on | 2145 // The way the effect interpolates the offset-to-ellipse/circle-center attri bute only works on |
2122 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r ect of the nine- | 2146 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r ect of the nine- |
2123 // patch will have fractional coverage. This only matters when the interior is actually filled. | 2147 // patch will have fractional coverage. This only matters when the interior is actually filled. |
2124 // We could consider falling back to rect rendering here, since a tiny radiu s is | 2148 // We could consider falling back to rect rendering here, since a tiny radiu s is |
2125 // indistinguishable from a square corner. | 2149 // indistinguishable from a square corner. |
2126 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 2150 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
2127 return false; | 2151 return NULL; |
2128 } | 2152 } |
2129 | 2153 |
2130 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); | 2154 GrIndexBuffer* indexBuffer = create_rrect_indexbuffer(strokeRRectIndexBuffer , |
2155 rrectIndexBuffer, | |
2156 isStrokeOnly, | |
2157 gpu); | |
2131 if (NULL == indexBuffer) { | 2158 if (NULL == indexBuffer) { |
2132 SkDebugf("Failed to create index buffer!\n"); | 2159 SkDebugf("Failed to create index buffer!\n"); |
2133 return false; | 2160 return NULL; |
2134 } | 2161 } |
2135 | 2162 |
2136 // if the corners are circles, use the circle renderer | 2163 // if the corners are circles, use the circle renderer |
2137 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius ) { | 2164 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius ) { |
2138 SkScalar innerRadius = 0.0f; | 2165 SkScalar innerRadius = 0.0f; |
2139 SkScalar outerRadius = xRadius; | 2166 SkScalar outerRadius = xRadius; |
2140 SkScalar halfWidth = 0; | 2167 SkScalar halfWidth = 0; |
2141 if (hasStroke) { | 2168 if (hasStroke) { |
2142 if (SkScalarNearlyZero(scaledStroke.fX)) { | 2169 if (SkScalarNearlyZero(scaledStroke.fX)) { |
2143 halfWidth = SK_ScalarHalf; | 2170 halfWidth = SK_ScalarHalf; |
2144 } else { | 2171 } else { |
2145 halfWidth = SkScalarHalf(scaledStroke.fX); | 2172 halfWidth = SkScalarHalf(scaledStroke.fX); |
2146 } | 2173 } |
2147 | 2174 |
2148 if (isStrokeOnly) { | 2175 if (isStrokeOnly) { |
2149 innerRadius = xRadius - halfWidth; | 2176 innerRadius = xRadius - halfWidth; |
2150 } | 2177 } |
2151 outerRadius += halfWidth; | 2178 outerRadius += halfWidth; |
2152 bounds.outset(halfWidth, halfWidth); | 2179 bounds->outset(halfWidth, halfWidth); |
2153 } | 2180 } |
2154 | 2181 |
2155 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 2182 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
2156 | 2183 |
2157 // The radii are outset for two reasons. First, it allows the shader to simply perform | 2184 // The radii are outset for two reasons. First, it allows the shader to simply perform |
2158 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. | 2185 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. |
2159 // Second, the outer radius is used to compute the verts of the bounding box that is | 2186 // Second, the outer radius is used to compute the verts of the bounding box that is |
2160 // rendered and the outset ensures the box will cover all partially cove red by the rrect | 2187 // rendered and the outset ensures the box will cover all partially cove red by the rrect |
2161 // corners. | 2188 // corners. |
2162 outerRadius += SK_ScalarHalf; | 2189 outerRadius += SK_ScalarHalf; |
2163 innerRadius -= SK_ScalarHalf; | 2190 innerRadius -= SK_ScalarHalf; |
2164 | 2191 |
2165 // Expand the rect so all the pixels will be captured. | 2192 // Expand the rect so all the pixels will be captured. |
2166 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 2193 bounds->outset(SK_ScalarHalf, SK_ScalarHalf); |
2167 | 2194 |
2168 RRectCircleRendererBatch::Geometry geometry; | 2195 RRectCircleRendererBatch::Geometry geometry; |
2169 geometry.fViewMatrix = viewMatrix; | 2196 geometry.fViewMatrix = viewMatrix; |
2170 geometry.fColor = color; | 2197 geometry.fColor = color; |
2171 geometry.fInnerRadius = innerRadius; | 2198 geometry.fInnerRadius = innerRadius; |
2172 geometry.fOuterRadius = outerRadius; | 2199 geometry.fOuterRadius = outerRadius; |
2173 geometry.fStroke = isStrokeOnly; | 2200 geometry.fStroke = isStrokeOnly; |
2174 geometry.fDevBounds = bounds; | 2201 geometry.fDevBounds = *bounds; |
2175 | 2202 |
2176 SkAutoTUnref<GrBatch> batch(RRectCircleRendererBatch::Create(geometry, i ndexBuffer)); | 2203 return RRectCircleRendererBatch::Create(geometry, indexBuffer); |
2177 target->drawBatch(pipelineBuilder, batch, &bounds); | |
2178 | 2204 |
2179 // otherwise we use the ellipse renderer | 2205 // otherwise we use the ellipse renderer |
2180 } else { | 2206 } else { |
2181 SkScalar innerXRadius = 0.0f; | 2207 SkScalar innerXRadius = 0.0f; |
2182 SkScalar innerYRadius = 0.0f; | 2208 SkScalar innerYRadius = 0.0f; |
2183 if (hasStroke) { | 2209 if (hasStroke) { |
2184 if (SkScalarNearlyZero(scaledStroke.length())) { | 2210 if (SkScalarNearlyZero(scaledStroke.length())) { |
2185 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 2211 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
2186 } else { | 2212 } else { |
2187 scaledStroke.scale(SK_ScalarHalf); | 2213 scaledStroke.scale(SK_ScalarHalf); |
2188 } | 2214 } |
2189 | 2215 |
2190 // we only handle thick strokes for near-circular ellipses | 2216 // we only handle thick strokes for near-circular ellipses |
2191 if (scaledStroke.length() > SK_ScalarHalf && | 2217 if (scaledStroke.length() > SK_ScalarHalf && |
2192 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad ius)) { | 2218 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad ius)) { |
2193 return false; | 2219 return NULL; |
2194 } | 2220 } |
2195 | 2221 |
2196 // we don't handle it if curvature of the stroke is less than curvat ure of the ellipse | 2222 // we don't handle it if curvature of the stroke is less than curvat ure of the ellipse |
2197 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok e.fY)*xRadius || | 2223 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok e.fY)*xRadius || |
2198 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok e.fX)*yRadius) { | 2224 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok e.fX)*yRadius) { |
2199 return false; | 2225 return NULL; |
2200 } | 2226 } |
2201 | 2227 |
2202 // this is legit only if scale & translation (which should be the ca se at the moment) | 2228 // this is legit only if scale & translation (which should be the ca se at the moment) |
2203 if (isStrokeOnly) { | 2229 if (isStrokeOnly) { |
2204 innerXRadius = xRadius - scaledStroke.fX; | 2230 innerXRadius = xRadius - scaledStroke.fX; |
2205 innerYRadius = yRadius - scaledStroke.fY; | 2231 innerYRadius = yRadius - scaledStroke.fY; |
2206 } | 2232 } |
2207 | 2233 |
2208 xRadius += scaledStroke.fX; | 2234 xRadius += scaledStroke.fX; |
2209 yRadius += scaledStroke.fY; | 2235 yRadius += scaledStroke.fY; |
2210 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 2236 bounds->outset(scaledStroke.fX, scaledStroke.fY); |
2211 } | 2237 } |
2212 | 2238 |
2213 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 2239 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
2214 | 2240 |
2215 // Expand the rect so all the pixels will be captured. | 2241 // Expand the rect so all the pixels will be captured. |
2216 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 2242 bounds->outset(SK_ScalarHalf, SK_ScalarHalf); |
2217 | 2243 |
2218 RRectEllipseRendererBatch::Geometry geometry; | 2244 RRectEllipseRendererBatch::Geometry geometry; |
2219 geometry.fViewMatrix = viewMatrix; | 2245 geometry.fViewMatrix = viewMatrix; |
2220 geometry.fColor = color; | 2246 geometry.fColor = color; |
2221 geometry.fXRadius = xRadius; | 2247 geometry.fXRadius = xRadius; |
2222 geometry.fYRadius = yRadius; | 2248 geometry.fYRadius = yRadius; |
2223 geometry.fInnerXRadius = innerXRadius; | 2249 geometry.fInnerXRadius = innerXRadius; |
2224 geometry.fInnerYRadius = innerYRadius; | 2250 geometry.fInnerYRadius = innerYRadius; |
2225 geometry.fStroke = isStrokeOnly; | 2251 geometry.fStroke = isStrokeOnly; |
2226 geometry.fDevBounds = bounds; | 2252 geometry.fDevBounds = *bounds; |
2227 | 2253 |
2228 SkAutoTUnref<GrBatch> batch(RRectEllipseRendererBatch::Create(geometry, indexBuffer)); | 2254 return RRectEllipseRendererBatch::Create(geometry, indexBuffer); |
2229 target->drawBatch(pipelineBuilder, batch, &bounds); | |
2230 } | 2255 } |
2256 } | |
2257 | |
2258 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, | |
2259 GrPipelineBuilder* pipelineBuilder, | |
2260 GrColor color, | |
2261 const SkMatrix& viewMatrix, | |
2262 bool useAA, | |
2263 const SkRRect& rrect, | |
2264 const SkStrokeRec& stroke) { | |
2265 if (rrect.isOval()) { | |
2266 return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(), | |
2267 stroke); | |
2268 } | |
2269 | |
2270 bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisa mpled(); | |
2271 | |
2272 // only anti-aliased rrects for now | |
2273 if (!useCoverageAA) { | |
2274 return false; | |
2275 } | |
2276 | |
2277 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { | |
2278 return false; | |
2279 } | |
2280 | |
2281 SkRect bounds; | |
2282 SkAutoTUnref<GrBatch> batch(create_rrect_batch(color, viewMatrix, rrect, str oke, &bounds, | |
2283 &fStrokeRRectIndexBuffer, &fR RectIndexBuffer, | |
2284 fGpu)); | |
2285 if (!batch) { | |
2286 return false; | |
2287 } | |
2288 | |
2289 target->drawBatch(pipelineBuilder, batch, &bounds); | |
2231 return true; | 2290 return true; |
2232 } | 2291 } |
2292 | |
2293 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
2294 | |
2295 #ifdef GR_TEST_UTILS | |
2296 | |
2297 static SkStrokeRec random_strokerec(SkRandom* random) { | |
2298 SkStrokeRec::InitStyle style = | |
2299 SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_Init Style + 1)); | |
2300 SkStrokeRec rec(style); | |
2301 bool strokeAndFill = random->nextBool(); | |
robertphillips
2015/04/30 14:07:32
Should probably also have a very wide stroke - 10.
| |
2302 SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f; | |
2303 rec.setStrokeStyle(strokeWidth, strokeAndFill); | |
2304 return rec; | |
2305 } | |
2306 | |
2307 BATCH_TEST_DEFINE(CircleBatch) { | |
2308 SkMatrix viewMatrix = GrTest::TestMatrix(random); | |
2309 GrColor color = GrRandomColor(random); | |
2310 bool useCoverageAA = random->nextBool(); | |
2311 SkRect circle = GrTest::TestRect(random); | |
2312 SkRect bounds; // unused | |
2313 return create_circle_batch(color, viewMatrix, useCoverageAA, circle, random_ strokerec(random), | |
2314 &bounds); | |
2315 } | |
2316 | |
2317 BATCH_TEST_DEFINE(EllipseBatch) { | |
2318 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | |
2319 GrColor color = GrRandomColor(random); | |
2320 bool useCoverageAA = random->nextBool(); | |
2321 SkRect ellipse = GrTest::TestRect(random); | |
2322 SkRect bounds; // unused | |
2323 return create_ellipse_batch(color, viewMatrix, useCoverageAA, ellipse, | |
2324 random_strokerec(random), &bounds); | |
2325 } | |
2326 | |
2327 BATCH_TEST_DEFINE(DIEllipseBatch) { | |
2328 SkMatrix viewMatrix = GrTest::TestMatrix(random); | |
2329 GrColor color = GrRandomColor(random); | |
2330 bool useCoverageAA = random->nextBool(); | |
2331 SkRect ellipse = GrTest::TestRect(random); | |
2332 SkRect bounds; // unused | |
2333 return create_diellipse_batch(color, viewMatrix, useCoverageAA, ellipse, | |
2334 random_strokerec(random), &bounds); | |
2335 } | |
2336 | |
2337 BATCH_TEST_DEFINE(RRectBatch) { | |
2338 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | |
2339 GrColor color = GrRandomColor(random); | |
2340 const SkRRect& rrect = GrTest::TestRRectSimple(random); | |
2341 | |
2342 static GrIndexBuffer* gStrokeRRectIndexBuffer; | |
2343 static GrIndexBuffer* gRRectIndexBuffer; | |
2344 SkRect bounds; | |
2345 return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random) , &bounds, | |
2346 &gStrokeRRectIndexBuffer, &gRRectIndexBuffer, cont ext->getGpu()); | |
2347 } | |
2348 | |
2349 #endif | |
OLD | NEW |