Chromium Code Reviews| 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 |