| 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 "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
| (...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 if (hasStroke) { | 1039 if (hasStroke) { |
| 1040 if (SkScalarNearlyZero(scaledStroke.length())) { | 1040 if (SkScalarNearlyZero(scaledStroke.length())) { |
| 1041 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1041 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
| 1042 } else { | 1042 } else { |
| 1043 scaledStroke.scale(SK_ScalarHalf); | 1043 scaledStroke.scale(SK_ScalarHalf); |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 // we only handle thick strokes for near-circular ellipses | 1046 // we only handle thick strokes for near-circular ellipses |
| 1047 if (scaledStroke.length() > SK_ScalarHalf && | 1047 if (scaledStroke.length() > SK_ScalarHalf && |
| 1048 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { | 1048 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { |
| 1049 return NULL; | 1049 return nullptr; |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse | 1052 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse |
| 1053 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY
)*xRadius || | 1053 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY
)*xRadius || |
| 1054 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX
)*yRadius) { | 1054 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX
)*yRadius) { |
| 1055 return NULL; | 1055 return nullptr; |
| 1056 } | 1056 } |
| 1057 | 1057 |
| 1058 // this is legit only if scale & translation (which should be the case a
t the moment) | 1058 // this is legit only if scale & translation (which should be the case a
t the moment) |
| 1059 if (isStrokeOnly) { | 1059 if (isStrokeOnly) { |
| 1060 innerXRadius = xRadius - scaledStroke.fX; | 1060 innerXRadius = xRadius - scaledStroke.fX; |
| 1061 innerYRadius = yRadius - scaledStroke.fY; | 1061 innerYRadius = yRadius - scaledStroke.fY; |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 xRadius += scaledStroke.fX; | 1064 xRadius += scaledStroke.fX; |
| 1065 yRadius += scaledStroke.fY; | 1065 yRadius += scaledStroke.fY; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 | 1279 |
| 1280 if (SkScalarNearlyZero(strokeWidth)) { | 1280 if (SkScalarNearlyZero(strokeWidth)) { |
| 1281 strokeWidth = SK_ScalarHalf; | 1281 strokeWidth = SK_ScalarHalf; |
| 1282 } else { | 1282 } else { |
| 1283 strokeWidth *= SK_ScalarHalf; | 1283 strokeWidth *= SK_ScalarHalf; |
| 1284 } | 1284 } |
| 1285 | 1285 |
| 1286 // we only handle thick strokes for near-circular ellipses | 1286 // we only handle thick strokes for near-circular ellipses |
| 1287 if (strokeWidth > SK_ScalarHalf && | 1287 if (strokeWidth > SK_ScalarHalf && |
| 1288 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { | 1288 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { |
| 1289 return NULL; | 1289 return nullptr; |
| 1290 } | 1290 } |
| 1291 | 1291 |
| 1292 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse | 1292 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse |
| 1293 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || | 1293 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || |
| 1294 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { | 1294 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { |
| 1295 return NULL; | 1295 return nullptr; |
| 1296 } | 1296 } |
| 1297 | 1297 |
| 1298 // set inner radius (if needed) | 1298 // set inner radius (if needed) |
| 1299 if (SkStrokeRec::kStroke_Style == style) { | 1299 if (SkStrokeRec::kStroke_Style == style) { |
| 1300 innerXRadius = xRadius - strokeWidth; | 1300 innerXRadius = xRadius - strokeWidth; |
| 1301 innerYRadius = yRadius - strokeWidth; | 1301 innerYRadius = yRadius - strokeWidth; |
| 1302 } | 1302 } |
| 1303 | 1303 |
| 1304 xRadius += strokeWidth; | 1304 xRadius += strokeWidth; |
| 1305 yRadius += strokeWidth; | 1305 yRadius += strokeWidth; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1408 if (!viewMatrix.isIdentity()) { | 1408 if (!viewMatrix.isIdentity()) { |
| 1409 if (!origInner.transform(viewMatrix, inner.writable())) { | 1409 if (!origInner.transform(viewMatrix, inner.writable())) { |
| 1410 return false; | 1410 return false; |
| 1411 } | 1411 } |
| 1412 } | 1412 } |
| 1413 GrPrimitiveEdgeType edgeType = applyAA ? | 1413 GrPrimitiveEdgeType edgeType = applyAA ? |
| 1414 kInverseFillAA_GrProcessorEdgeType : | 1414 kInverseFillAA_GrProcessorEdgeType : |
| 1415 kInverseFillBW_GrProcessorEdgeType; | 1415 kInverseFillBW_GrProcessorEdgeType; |
| 1416 // TODO this needs to be a geometry processor | 1416 // TODO this needs to be a geometry processor |
| 1417 GrFragmentProcessor* fp = GrRRectEffect::Create(edgeType, *inner); | 1417 GrFragmentProcessor* fp = GrRRectEffect::Create(edgeType, *inner); |
| 1418 if (NULL == fp) { | 1418 if (nullptr == fp) { |
| 1419 return false; | 1419 return false; |
| 1420 } | 1420 } |
| 1421 arfps.set(&pipelineBuilder); | 1421 arfps.set(&pipelineBuilder); |
| 1422 arfps.addCoverageFragmentProcessor(fp)->unref(); | 1422 arfps.addCoverageFragmentProcessor(fp)->unref(); |
| 1423 } | 1423 } |
| 1424 | 1424 |
| 1425 SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle); | 1425 SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle); |
| 1426 if (DrawRRect(target, pipelineBuilder, color, viewMatrix, useAA, origOuter,
fillRec)) { | 1426 if (DrawRRect(target, pipelineBuilder, color, viewMatrix, useAA, origOuter,
fillRec)) { |
| 1427 return true; | 1427 return true; |
| 1428 } | 1428 } |
| 1429 | 1429 |
| 1430 SkASSERT(!origOuter.isEmpty()); | 1430 SkASSERT(!origOuter.isEmpty()); |
| 1431 SkTCopyOnFirstWrite<SkRRect> outer(origOuter); | 1431 SkTCopyOnFirstWrite<SkRRect> outer(origOuter); |
| 1432 if (!viewMatrix.isIdentity()) { | 1432 if (!viewMatrix.isIdentity()) { |
| 1433 if (!origOuter.transform(viewMatrix, outer.writable())) { | 1433 if (!origOuter.transform(viewMatrix, outer.writable())) { |
| 1434 return false; | 1434 return false; |
| 1435 } | 1435 } |
| 1436 } | 1436 } |
| 1437 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : | 1437 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : |
| 1438 kFillBW_GrProcessorEdgeType; | 1438 kFillBW_GrProcessorEdgeType; |
| 1439 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); | 1439 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); |
| 1440 if (NULL == effect) { | 1440 if (nullptr == effect) { |
| 1441 return false; | 1441 return false; |
| 1442 } | 1442 } |
| 1443 if (!arfps.isSet()) { | 1443 if (!arfps.isSet()) { |
| 1444 arfps.set(&pipelineBuilder); | 1444 arfps.set(&pipelineBuilder); |
| 1445 } | 1445 } |
| 1446 | 1446 |
| 1447 SkMatrix invert; | 1447 SkMatrix invert; |
| 1448 if (!viewMatrix.invert(&invert)) { | 1448 if (!viewMatrix.invert(&invert)) { |
| 1449 return false; | 1449 return false; |
| 1450 } | 1450 } |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 scaledStroke.set(1, 1); | 1856 scaledStroke.set(1, 1); |
| 1857 } else { | 1857 } else { |
| 1858 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc
aleX] + | 1858 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc
aleX] + |
| 1859 viewMatrix[SkMatrix::kMSk
ewY])); | 1859 viewMatrix[SkMatrix::kMSk
ewY])); |
| 1860 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk
ewX] + | 1860 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk
ewX] + |
| 1861 viewMatrix[SkMatrix::kMSc
aleY])); | 1861 viewMatrix[SkMatrix::kMSc
aleY])); |
| 1862 } | 1862 } |
| 1863 | 1863 |
| 1864 // if half of strokewidth is greater than radius, we don't handle that r
ight now | 1864 // if half of strokewidth is greater than radius, we don't handle that r
ight now |
| 1865 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { | 1865 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { |
| 1866 return NULL; | 1866 return nullptr; |
| 1867 } | 1867 } |
| 1868 } | 1868 } |
| 1869 | 1869 |
| 1870 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on | 1870 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on |
| 1871 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- | 1871 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- |
| 1872 // patch will have fractional coverage. This only matters when the interior
is actually filled. | 1872 // patch will have fractional coverage. This only matters when the interior
is actually filled. |
| 1873 // We could consider falling back to rect rendering here, since a tiny radiu
s is | 1873 // We could consider falling back to rect rendering here, since a tiny radiu
s is |
| 1874 // indistinguishable from a square corner. | 1874 // indistinguishable from a square corner. |
| 1875 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 1875 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
| 1876 return NULL; | 1876 return nullptr; |
| 1877 } | 1877 } |
| 1878 | 1878 |
| 1879 // if the corners are circles, use the circle renderer | 1879 // if the corners are circles, use the circle renderer |
| 1880 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { | 1880 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { |
| 1881 SkScalar innerRadius = 0.0f; | 1881 SkScalar innerRadius = 0.0f; |
| 1882 SkScalar outerRadius = xRadius; | 1882 SkScalar outerRadius = xRadius; |
| 1883 SkScalar halfWidth = 0; | 1883 SkScalar halfWidth = 0; |
| 1884 if (hasStroke) { | 1884 if (hasStroke) { |
| 1885 if (SkScalarNearlyZero(scaledStroke.fX)) { | 1885 if (SkScalarNearlyZero(scaledStroke.fX)) { |
| 1886 halfWidth = SK_ScalarHalf; | 1886 halfWidth = SK_ScalarHalf; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 if (hasStroke) { | 1924 if (hasStroke) { |
| 1925 if (SkScalarNearlyZero(scaledStroke.length())) { | 1925 if (SkScalarNearlyZero(scaledStroke.length())) { |
| 1926 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1926 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
| 1927 } else { | 1927 } else { |
| 1928 scaledStroke.scale(SK_ScalarHalf); | 1928 scaledStroke.scale(SK_ScalarHalf); |
| 1929 } | 1929 } |
| 1930 | 1930 |
| 1931 // we only handle thick strokes for near-circular ellipses | 1931 // we only handle thick strokes for near-circular ellipses |
| 1932 if (scaledStroke.length() > SK_ScalarHalf && | 1932 if (scaledStroke.length() > SK_ScalarHalf && |
| 1933 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad
ius)) { | 1933 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad
ius)) { |
| 1934 return NULL; | 1934 return nullptr; |
| 1935 } | 1935 } |
| 1936 | 1936 |
| 1937 // we don't handle it if curvature of the stroke is less than curvat
ure of the ellipse | 1937 // we don't handle it if curvature of the stroke is less than curvat
ure of the ellipse |
| 1938 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok
e.fY)*xRadius || | 1938 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok
e.fY)*xRadius || |
| 1939 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok
e.fX)*yRadius) { | 1939 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok
e.fX)*yRadius) { |
| 1940 return NULL; | 1940 return nullptr; |
| 1941 } | 1941 } |
| 1942 | 1942 |
| 1943 // this is legit only if scale & translation (which should be the ca
se at the moment) | 1943 // this is legit only if scale & translation (which should be the ca
se at the moment) |
| 1944 if (isStrokeOnly) { | 1944 if (isStrokeOnly) { |
| 1945 innerXRadius = xRadius - scaledStroke.fX; | 1945 innerXRadius = xRadius - scaledStroke.fX; |
| 1946 innerYRadius = yRadius - scaledStroke.fY; | 1946 innerYRadius = yRadius - scaledStroke.fY; |
| 1947 } | 1947 } |
| 1948 | 1948 |
| 1949 xRadius += scaledStroke.fX; | 1949 xRadius += scaledStroke.fX; |
| 1950 yRadius += scaledStroke.fY; | 1950 yRadius += scaledStroke.fY; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2033 } | 2033 } |
| 2034 | 2034 |
| 2035 DRAW_BATCH_TEST_DEFINE(RRectBatch) { | 2035 DRAW_BATCH_TEST_DEFINE(RRectBatch) { |
| 2036 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | 2036 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
| 2037 GrColor color = GrRandomColor(random); | 2037 GrColor color = GrRandomColor(random); |
| 2038 const SkRRect& rrect = GrTest::TestRRectSimple(random); | 2038 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
| 2039 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); | 2039 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); |
| 2040 } | 2040 } |
| 2041 | 2041 |
| 2042 #endif | 2042 #endif |
| OLD | NEW |