GrPathUtils.cpp revision 4dbbd04314cc0606f8d3bafe515c97e52c180f73
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 69d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org */ 79d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 89d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org#include "GrPathUtils.h" 9fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org 10d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips#include "GrTypes.h" 1169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkGeometry.h" 124dbbd04314cc0606f8d3bafe515c97e52c180f73halcanary#include "SkMathPriv.h" 139d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 1481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.comSkScalar GrPathUtils::scaleToleranceToSrc(SkScalar devTol, 15b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix& viewM, 16fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkRect& pathBounds) { 17181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com // In order to tesselate the path we get a bound on how much the matrix can 181878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org // scale when mapping to screen coordinates. 191878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org SkScalar stretch = viewM.getMaxScale(); 2081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar srcTol = devTol; 21181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com 22181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com if (stretch < 0) { 23383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // take worst case mapRadius amoung four corners. 24383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // (less than perfect) 25383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com for (int i = 0; i < 4; ++i) { 26b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix mat; 27383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com mat.setTranslate((i % 2) ? pathBounds.fLeft : pathBounds.fRight, 28383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com (i < 2) ? pathBounds.fTop : pathBounds.fBottom); 29383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com mat.postConcat(viewM); 30383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com stretch = SkMaxScalar(stretch, mat.mapRadius(SK_Scalar1)); 31383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com } 32181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com } 3380ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed return srcTol / stretch; 34181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com} 35181e9bd9484ece4132e0cc5cfcff602134e5489dbsalomon@google.com 36b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.comstatic const int MAX_POINTS_PER_CURVE = 1 << 10; 374b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgstatic const SkScalar gMinCurveTol = 0.0001f; 389d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 39972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orguint32_t GrPathUtils::quadraticPointCount(const SkPoint points[], 4081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar tol) { 41c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com if (tol < gMinCurveTol) { 42afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.com tol = gMinCurveTol; 43c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com } 44f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(tol > 0); 45c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com 4681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]); 47c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com if (d <= tol) { 489d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return 1; 499d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } else { 509d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org // Each time we subdivide, d should be cut in 4. So we need to 519d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x) 529d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org // points. 539d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org // 2^(log4(x)) = sqrt(x); 5480ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar divSqrt = SkScalarSqrt(d / tol); 555a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel if (((SkScalar)SK_MaxS32) <= divSqrt) { 565a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel return MAX_POINTS_PER_CURVE; 575a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel } else { 585a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel int temp = SkScalarCeilToInt(divSqrt); 595a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel int pow2 = GrNextPow2(temp); 605a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // Because of NaNs & INFs we can wind up with a degenerate temp 615a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // such that pow2 comes out negative. Also, our point generator 625a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // will always output at least one pt. 635a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel if (pow2 < 1) { 645a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel pow2 = 1; 655a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel } 665a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel return SkTMin(pow2, MAX_POINTS_PER_CURVE); 6761f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com } 689d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 699d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org} 709d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 71972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orguint32_t GrPathUtils::generateQuadraticPoints(const SkPoint& p0, 72972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint& p1, 73972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint& p2, 7481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar tolSqd, 75972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint** points, 76c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com uint32_t pointsLeft) { 779d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org if (pointsLeft < 2 || 789d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) { 799d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org (*points)[0] = p2; 809d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org *points += 1; 819d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return 1; 829d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 839d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 84972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint q[] = { 8581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, 8681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, 879d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org }; 88972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) }; 899d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 909d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointsLeft >>= 1; 919d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft); 929d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft); 939d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return a + b; 949d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org} 959d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 96972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orguint32_t GrPathUtils::cubicPointCount(const SkPoint points[], 9781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar tol) { 98c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com if (tol < gMinCurveTol) { 99afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.com tol = gMinCurveTol; 100c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com } 101f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(tol > 0); 102c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com 103972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkScalar d = SkTMax( 104c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]), 105c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com points[2].distanceToLineSegmentBetweenSqd(points[0], points[3])); 1062047f00e4698f83499ab91911999a65c21a951c9epoger@google.com d = SkScalarSqrt(d); 107c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com if (d <= tol) { 1089d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return 1; 1099d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } else { 11080ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar divSqrt = SkScalarSqrt(d / tol); 1115a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel if (((SkScalar)SK_MaxS32) <= divSqrt) { 1125a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel return MAX_POINTS_PER_CURVE; 1135a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel } else { 11480ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed int temp = SkScalarCeilToInt(SkScalarSqrt(d / tol)); 1155a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel int pow2 = GrNextPow2(temp); 1165a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // Because of NaNs & INFs we can wind up with a degenerate temp 1175a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // such that pow2 comes out negative. Also, our point generator 1185a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel // will always output at least one pt. 1195a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel if (pow2 < 1) { 1205a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel pow2 = 1; 1215a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel } 1225a23a14b1fbc7503bdeff83e4b45ae7c258c6e96egdaniel return SkTMin(pow2, MAX_POINTS_PER_CURVE); 12361f3bde1ba114e7b39b53411f4aa31ed0875d159bsalomon@google.com } 1249d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 1259d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org} 1269d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 127972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orguint32_t GrPathUtils::generateCubicPoints(const SkPoint& p0, 128972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint& p1, 129972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint& p2, 130972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint& p3, 13181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar tolSqd, 132972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint** points, 133c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com uint32_t pointsLeft) { 1349d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org if (pointsLeft < 2 || 1359d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd && 1369d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) { 137f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips (*points)[0] = p3; 138f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips *points += 1; 139f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips return 1; 140f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips } 141972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint q[] = { 14281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, 14381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, 14481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) } 1459d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org }; 146972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint r[] = { 14781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) }, 14881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) } 1499d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org }; 150972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) }; 1519d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointsLeft >>= 1; 1529d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft); 1539d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft); 1549d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return a + b; 1559d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org} 1569d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 1578d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comint GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths, 15881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar tol) { 159c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com if (tol < gMinCurveTol) { 160afec7ba75962517b17293799d3fc70d39fa7dbf2tomhudson@google.com tol = gMinCurveTol; 161c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com } 162f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(tol > 0); 163c10a88825d119054a9f4e7b7af7a3f887e30ab6btomhudson@google.com 1649d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org int pointCount = 0; 1659d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org *subpaths = 1; 1669d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 1679d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org bool first = true; 1689d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 169129b8e3237b80b9d258a8f48e8f54c0073cafbdcsenorblanco@chromium.org SkPath::Iter iter(path, false); 17094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com SkPath::Verb verb; 1719d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 172972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint pts[4]; 17394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 1749d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org 17594b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 17694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: 1779d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointCount += 1; 1789d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org break; 179af18a09d13611526c4217656c98947f9067cb07aegdaniel case SkPath::kConic_Verb: { 180af18a09d13611526c4217656c98947f9067cb07aegdaniel SkScalar weight = iter.conicWeight(); 181af18a09d13611526c4217656c98947f9067cb07aegdaniel SkAutoConicToQuads converter; 182af18a09d13611526c4217656c98947f9067cb07aegdaniel const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.25f); 183af18a09d13611526c4217656c98947f9067cb07aegdaniel for (int i = 0; i < converter.countQuads(); ++i) { 184af18a09d13611526c4217656c98947f9067cb07aegdaniel pointCount += quadraticPointCount(quadPts + 2*i, tol); 185af18a09d13611526c4217656c98947f9067cb07aegdaniel } 186af18a09d13611526c4217656c98947f9067cb07aegdaniel } 18794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kQuad_Verb: 1889d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointCount += quadraticPointCount(pts, tol); 1899d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org break; 19094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: 1919d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointCount += cubicPointCount(pts, tol); 1929d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org break; 19394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kMove_Verb: 1949d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org pointCount += 1; 1959d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org if (!first) { 1969d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org ++(*subpaths); 1979d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 1989d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org break; 1999d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org default: 2009d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org break; 2019d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 2029d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org first = false; 2039d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org } 2049d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org return pointCount; 2059d18b7873ce9b44f130a41e0cbd0a3df76ab9adfsenorblanco@chromium.org} 20669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 207972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgvoid GrPathUtils::QuadUVMatrix::set(const SkPoint qPts[3]) { 2081971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com SkMatrix m; 209dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // We want M such that M * xy_pt = uv_pt 210dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // We know M * control_pts = [0 1/2 1] 211dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // [0 0 1] 212dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // [1 1 1] 213f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // And control_pts = [x0 x1 x2] 214f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // [y0 y1 y2] 215f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // [1 1 1 ] 216dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // We invert the control pt matrix and post concat to both sides to get M. 217f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // Using the known form of the control point matrix and the result, we can 218f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // optimize and improve precision. 219f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 220f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double x0 = qPts[0].fX; 221f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double y0 = qPts[0].fY; 222f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double x1 = qPts[1].fX; 223f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double y1 = qPts[1].fY; 224f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double x2 = qPts[2].fX; 225f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double y2 = qPts[2].fY; 226f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double det = x0*y1 - y0*x1 + x2*y0 - y2*x0 + x1*y2 - y1*x2; 227f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 2288491d24bdc3f48f67475c12c60babb9f9dba8047skia.committer@gmail.com if (!sk_float_isfinite(det) 229f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org || SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 230dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // The quad is degenerate. Hopefully this is rare. Find the pts that are 231dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // farthest apart to compute a line (unless it is really a pt). 232dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com SkScalar maxD = qPts[0].distanceToSqd(qPts[1]); 233dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com int maxEdge = 0; 234dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com SkScalar d = qPts[1].distanceToSqd(qPts[2]); 235dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com if (d > maxD) { 236dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com maxD = d; 237dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com maxEdge = 1; 238dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } 239dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com d = qPts[2].distanceToSqd(qPts[0]); 240dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com if (d > maxD) { 241dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com maxD = d; 242dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com maxEdge = 2; 243dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } 244dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // We could have a tolerance here, not sure if it would improve anything 245dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com if (maxD > 0) { 246dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // Set the matrix to give (u = 0, v = distance_to_line) 247972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector lineVec = qPts[(maxEdge + 1)%3] - qPts[maxEdge]; 24820e542e00eccaf7b9e81964692a47086e6aaf568bsalomon@google.com // when looking from the point 0 down the line we want positive 24920e542e00eccaf7b9e81964692a47086e6aaf568bsalomon@google.com // distances to be to the left. This matches the non-degenerate 25020e542e00eccaf7b9e81964692a47086e6aaf568bsalomon@google.com // case. 251972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org lineVec.setOrthog(lineVec, SkPoint::kLeft_Side); 252dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com lineVec.dot(qPts[0]); 2531971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com // first row 2541971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[0] = 0; 2551971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[1] = 0; 2561971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[2] = 0; 2571971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com // second row 2581971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[3] = lineVec.fX; 2591971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[4] = lineVec.fY; 2601971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[5] = -lineVec.dot(qPts[maxEdge]); 261dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } else { 262dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // It's a point. It should cover zero area. Just set the matrix such 263dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com // that (u, v) will always be far away from the quad. 2641971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[0] = 0; fM[1] = 0; fM[2] = 100.f; 2651971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[3] = 0; fM[4] = 0; fM[5] = 100.f; 266dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } 267dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } else { 268f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org double scale = 1.0/det; 269f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 270f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // compute adjugate matrix 27187a223401d8575d398eb369f7be7afdabbdfab08robertphillips double a2, a3, a4, a5, a6, a7, a8; 272f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a2 = x1*y2-x2*y1; 273f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 274f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a3 = y2-y0; 275f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a4 = x0-x2; 276f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a5 = x2*y0-x0*y2; 277f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 278f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a6 = y0-y1; 279f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a7 = x1-x0; 280f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org a8 = x0*y1-x1*y0; 281f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 2828491d24bdc3f48f67475c12c60babb9f9dba8047skia.committer@gmail.com // this performs the uv_pts*adjugate(control_pts) multiply, 283f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org // then does the scale by 1/det afterwards to improve precision 284f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMScaleX] = (float)((0.5*a3 + a6)*scale); 285f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMSkewX] = (float)((0.5*a4 + a7)*scale); 286f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMTransX] = (float)((0.5*a5 + a8)*scale); 287f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 288f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMSkewY] = (float)(a6*scale); 289f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMScaleY] = (float)(a7*scale); 290f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMTransY] = (float)(a8*scale); 291f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org 29287a223401d8575d398eb369f7be7afdabbdfab08robertphillips // kMPersp0 & kMPersp1 should algebraically be zero 29387a223401d8575d398eb369f7be7afdabbdfab08robertphillips m[SkMatrix::kMPersp0] = 0.0f; 29487a223401d8575d398eb369f7be7afdabbdfab08robertphillips m[SkMatrix::kMPersp1] = 0.0f; 295f543fd9e8c162b65fd04d1d9439b60911f8eb4c0commit-bot@chromium.org m[SkMatrix::kMPersp2] = (float)((a2 + a5 + a8)*scale); 2961971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com 2971971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com // It may not be normalized to have 1.0 in the bottom right 2981971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com float m33 = m.get(SkMatrix::kMPersp2); 2991971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com if (1.f != m33) { 3001971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com m33 = 1.f / m33; 3011971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[0] = m33 * m.get(SkMatrix::kMScaleX); 3021971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[1] = m33 * m.get(SkMatrix::kMSkewX); 3031971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[2] = m33 * m.get(SkMatrix::kMTransX); 3041971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[3] = m33 * m.get(SkMatrix::kMSkewY); 3051971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[4] = m33 * m.get(SkMatrix::kMScaleY); 3061971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[5] = m33 * m.get(SkMatrix::kMTransY); 3071971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com } else { 3081971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[0] = m.get(SkMatrix::kMScaleX); 3091971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[1] = m.get(SkMatrix::kMSkewX); 3101971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[2] = m.get(SkMatrix::kMTransX); 3111971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[3] = m.get(SkMatrix::kMSkewY); 3121971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[4] = m.get(SkMatrix::kMScaleY); 3131971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com fM[5] = m.get(SkMatrix::kMTransY); 3141971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com } 315dc3c78076ea279d4f6d502b3b42471e9b2bba48ebsalomon@google.com } 31669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 31769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 318139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 319139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 320139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org// k = (y2 - y0, x0 - x2, (x2 - x0)*y0 - (y2 - y0)*x0 ) 321139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org// l = (2*w * (y1 - y0), 2*w * (x0 - x1), 2*w * (x1*y0 - x0*y1)) 322139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org// m = (2*w * (y2 - y1), 2*w * (x1 - x2), 2*w * (x2*y1 - x1*y2)) 323139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.orgvoid GrPathUtils::getConicKLM(const SkPoint p[3], const SkScalar weight, SkScalar klm[9]) { 324139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org const SkScalar w2 = 2.f * weight; 325139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[0] = p[2].fY - p[0].fY; 326139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[1] = p[0].fX - p[2].fX; 327139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[2] = (p[2].fX - p[0].fX) * p[0].fY - (p[2].fY - p[0].fY) * p[0].fX; 328139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 329139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[3] = w2 * (p[1].fY - p[0].fY); 330139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[4] = w2 * (p[0].fX - p[1].fX); 331139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[5] = w2 * (p[1].fX * p[0].fY - p[0].fX * p[1].fY); 332139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 333139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[6] = w2 * (p[2].fY - p[1].fY); 334139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[7] = w2 * (p[1].fX - p[2].fX); 335139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[8] = w2 * (p[2].fX * p[1].fY - p[1].fX * p[2].fY); 336139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 337139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org // scale the max absolute value of coeffs to 10 338139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org SkScalar scale = 0.f; 339139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org for (int i = 0; i < 9; ++i) { 340139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org scale = SkMaxScalar(scale, SkScalarAbs(klm[i])); 341139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org } 342139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org SkASSERT(scale > 0.f); 343139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org scale = 10.f / scale; 344139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org for (int i = 0; i < 9; ++i) { 345139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org klm[i] *= scale; 346139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org } 347139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org} 348139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 349139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 350139484095f014ab08265c32337fddeeec6c0877dcommit-bot@chromium.org 35169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comnamespace { 352a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 353a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// a is the first control point of the cubic. 354a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// ab is the vector from a to the second control point. 355a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// dc is the vector from the fourth to the third control point. 356a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// d is the fourth control point. 357a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// p is the candidate quadratic control point. 358a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com// this assumes that the cubic doesn't inflect and is simple 359a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.combool is_point_within_cubic_tangents(const SkPoint& a, 360a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com const SkVector& ab, 361a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com const SkVector& dc, 362a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com const SkPoint& d, 363026beb52a29a620290fcfb24f1e7e9e75547b80freed SkPathPriv::FirstDirection dir, 364a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com const SkPoint p) { 365a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkVector ap = p - a; 366a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar apXab = ap.cross(ab); 367026beb52a29a620290fcfb24f1e7e9e75547b80freed if (SkPathPriv::kCW_FirstDirection == dir) { 368a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (apXab > 0) { 369a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 370a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 371a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } else { 372026beb52a29a620290fcfb24f1e7e9e75547b80freed SkASSERT(SkPathPriv::kCCW_FirstDirection == dir); 373a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (apXab < 0) { 374a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 375a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 376a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 377a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 378a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkVector dp = p - d; 379a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar dpXdc = dp.cross(dc); 380026beb52a29a620290fcfb24f1e7e9e75547b80freed if (SkPathPriv::kCW_FirstDirection == dir) { 381a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (dpXdc < 0) { 382a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 383a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 384a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } else { 385026beb52a29a620290fcfb24f1e7e9e75547b80freed SkASSERT(SkPathPriv::kCCW_FirstDirection == dir); 386a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (dpXdc > 0) { 387a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 388a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 389a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 390a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return true; 391a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com} 392a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 39369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comvoid convert_noninflect_cubic_to_quads(const SkPoint p[4], 394a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar toleranceSqd, 395a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com bool constrainWithinTangents, 396026beb52a29a620290fcfb24f1e7e9e75547b80freed SkPathPriv::FirstDirection dir, 39769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkTArray<SkPoint, true>* quads, 39869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com int sublevel = 0) { 39954ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com 40054ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com // Notation: Point a is always p[0]. Point b is p[1] unless p[1] == p[0], in which case it is 40154ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com // p[2]. Point d is always p[3]. Point c is p[2] unless p[2] == p[3], in which case it is p[1]. 40254ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com 403a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkVector ab = p[1] - p[0]; 404a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkVector dc = p[2] - p[3]; 405a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 406f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips if (ab.lengthSqd() < SK_ScalarNearlyZero) { 407f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips if (dc.lengthSqd() < SK_ScalarNearlyZero) { 408a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPoint* degQuad = quads->push_back_n(3); 409a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com degQuad[0] = p[0]; 410a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com degQuad[1] = p[0]; 411a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com degQuad[2] = p[3]; 412a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return; 413a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 414a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com ab = p[2] - p[0]; 415a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 416f08ce6cd53c5607ed068f755036b062a8693a8dcrobertphillips if (dc.lengthSqd() < SK_ScalarNearlyZero) { 417a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com dc = p[1] - p[3]; 418a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 419a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 4203935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // When the ab and cd tangents are degenerate or nearly parallel with vector from d to a the 4213935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // constraint that the quad point falls between the tangents becomes hard to enforce and we are 4223935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // likely to hit the max subdivision count. However, in this case the cubic is approaching a 4233935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // line and the accuracy of the quad point isn't so important. We check if the two middle cubic 4243935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // control points are very close to the baseline vector. If so then we just pick quadratic 4253935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // points on the control polygon. 42654ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com 42754ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com if (constrainWithinTangents) { 42854ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com SkVector da = p[0] - p[3]; 4293935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon bool doQuads = dc.lengthSqd() < SK_ScalarNearlyZero || 4303935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon ab.lengthSqd() < SK_ScalarNearlyZero; 4313935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon if (!doQuads) { 4323935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkScalar invDALengthSqd = da.lengthSqd(); 4333935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon if (invDALengthSqd > SK_ScalarNearlyZero) { 4343935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon invDALengthSqd = SkScalarInvert(invDALengthSqd); 4353935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // cross(ab, da)^2/length(da)^2 == sqd distance from b to line from d to a. 4363935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // same goes for point c using vector cd. 4373935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkScalar detABSqd = ab.cross(da); 4383935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon detABSqd = SkScalarSquare(detABSqd); 4393935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkScalar detDCSqd = dc.cross(da); 4403935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon detDCSqd = SkScalarSquare(detDCSqd); 4413935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon if (SkScalarMul(detABSqd, invDALengthSqd) < toleranceSqd && 4423935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkScalarMul(detDCSqd, invDALengthSqd) < toleranceSqd) { 4433935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon doQuads = true; 44454ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com } 44554ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com } 44654ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com } 4473935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon if (doQuads) { 4483935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkPoint b = p[0] + ab; 4493935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkPoint c = p[3] + dc; 4503935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkPoint mid = b + c; 4513935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon mid.scale(SK_ScalarHalf); 4523935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // Insert two quadratics to cover the case when ab points away from d and/or dc 4533935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon // points away from a. 4543935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon if (SkVector::DotProduct(da, dc) < 0 || SkVector::DotProduct(ab,da) > 0) { 4553935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkPoint* qpts = quads->push_back_n(6); 4563935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[0] = p[0]; 4573935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[1] = b; 4583935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[2] = mid; 4593935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[3] = mid; 4603935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[4] = c; 4613935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[5] = p[3]; 4623935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon } else { 4633935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon SkPoint* qpts = quads->push_back_n(3); 4643935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[0] = p[0]; 4653935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[1] = mid; 4663935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon qpts[2] = p[3]; 4673935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon } 4683935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon return; 4693935a7bfe64293edf9b06527f59d657ff4e280cbbsalomon } 47054ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com } 47154ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com 472a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2; 47369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com static const int kMaxSubdivs = 10; 47469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 475a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com ab.scale(kLengthScale); 476a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com dc.scale(kLengthScale); 47769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 478a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // e0 and e1 are extrapolations along vectors ab and dc. 47969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkVector c0 = p[0]; 48069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com c0 += ab; 48169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkVector c1 = p[3]; 48269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com c1 += dc; 48369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 48454ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com SkScalar dSqd = sublevel > kMaxSubdivs ? 0 : c0.distanceToSqd(c1); 485a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (dSqd < toleranceSqd) { 48669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPoint cAvg = c0; 48769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com cAvg += c1; 48869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com cAvg.scale(SK_ScalarHalf); 48969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 490a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com bool subdivide = false; 491a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 492a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (constrainWithinTangents && 493a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com !is_point_within_cubic_tangents(p[0], ab, dc, p[3], dir, cAvg)) { 49454ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com // choose a new cAvg that is the intersection of the two tangent lines. 495a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com ab.setOrthog(ab); 496a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar z0 = -ab.dot(p[0]); 497a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com dc.setOrthog(dc); 498a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar z1 = -dc.dot(p[3]); 499a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com cAvg.fX = SkScalarMul(ab.fY, z1) - SkScalarMul(z0, dc.fY); 500a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com cAvg.fY = SkScalarMul(z0, dc.fX) - SkScalarMul(ab.fX, z1); 501a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar z = SkScalarMul(ab.fX, dc.fY) - SkScalarMul(ab.fY, dc.fX); 502a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com z = SkScalarInvert(z); 503a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com cAvg.fX *= z; 504a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com cAvg.fY *= z; 505a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (sublevel <= kMaxSubdivs) { 506a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar d0Sqd = c0.distanceToSqd(cAvg); 507a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar d1Sqd = c1.distanceToSqd(cAvg); 50854ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com // We need to subdivide if d0 + d1 > tolerance but we have the sqd values. We know 50954ad851361c55466f1e4950585afc2aa6cf173c5bsalomon@google.com // the distances and tolerance can't be negative. 510a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // (d0 + d1)^2 > toleranceSqd 511a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // d0Sqd + 2*d0*d1 + d1Sqd > toleranceSqd 512a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkScalar d0d1 = SkScalarSqrt(SkScalarMul(d0Sqd, d1Sqd)); 513a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com subdivide = 2 * d0d1 + d0Sqd + d1Sqd > toleranceSqd; 514a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 515a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 516a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!subdivide) { 517a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 518a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com pts[0] = p[0]; 519a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com pts[1] = cAvg; 520a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com pts[2] = p[3]; 521a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return; 522a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 52369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 524a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPoint choppedPts[7]; 525a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkChopCubicAtHalf(p, choppedPts); 526a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com convert_noninflect_cubic_to_quads(choppedPts + 0, 527a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com toleranceSqd, 528a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com constrainWithinTangents, 529a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com dir, 530a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com quads, 531a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com sublevel + 1); 532a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com convert_noninflect_cubic_to_quads(choppedPts + 3, 533a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com toleranceSqd, 534a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com constrainWithinTangents, 535a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com dir, 536a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com quads, 537a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com sublevel + 1); 53869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 53969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 54069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 541972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgvoid GrPathUtils::convertCubicToQuads(const SkPoint p[4], 54269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkScalar tolScale, 54369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkTArray<SkPoint, true>* quads) { 54469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPoint chopped[10]; 54569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com int count = SkChopCubicAtInflections(p, chopped); 54669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 54718fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon const SkScalar tolSqd = SkScalarSquare(tolScale); 548a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com 54969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com for (int i = 0; i < count; ++i) { 55069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPoint* cubic = chopped + 3*i; 55118fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon // The direction param is ignored if the third param is false. 55218fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon convert_noninflect_cubic_to_quads(cubic, tolSqd, false, 55318fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkPathPriv::kCCW_FirstDirection, quads); 55469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 55518fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon} 55618fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon 55718fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomonvoid GrPathUtils::convertCubicToQuadsConstrainToTangents(const SkPoint p[4], 55818fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkScalar tolScale, 55918fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkPathPriv::FirstDirection dir, 56018fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkTArray<SkPoint, true>* quads) { 56118fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkPoint chopped[10]; 56218fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon int count = SkChopCubicAtInflections(p, chopped); 56369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 56418fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon const SkScalar tolSqd = SkScalarSquare(tolScale); 56518fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon 56618fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon for (int i = 0; i < count; ++i) { 56718fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon SkPoint* cubic = chopped + 3*i; 56818fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon convert_noninflect_cubic_to_quads(cubic, tolSqd, true, dir, quads); 56918fab30d7c4858ef2521e0380573aac5a21b2ed9bsalomon } 57069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 571858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 572858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 573858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 574858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// Solves linear system to extract klm 575858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// P.K = k (similarly for l, m) 576858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// Where P is matrix of control points 577858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// K is coefficients for the line K 578858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// k is vector of values of K evaluated at the control points 579858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// Solving for K, thus K = P^(-1) . k 580858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgstatic void calc_cubic_klm(const SkPoint p[4], const SkScalar controlK[4], 581858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar controlL[4], const SkScalar controlM[4], 582858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar k[3], SkScalar l[3], SkScalar m[3]) { 583858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkMatrix matrix; 584858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org matrix.setAll(p[0].fX, p[0].fY, 1.f, 585858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org p[1].fX, p[1].fY, 1.f, 586858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org p[2].fX, p[2].fY, 1.f); 587858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkMatrix inverse; 588858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (matrix.invert(&inverse)) { 589858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org inverse.mapHomogeneousPoints(k, controlK, 1); 590858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org inverse.mapHomogeneousPoints(l, controlL, 1); 591858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org inverse.mapHomogeneousPoints(m, controlM, 1); 592858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 593858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 594858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 595858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 596858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgstatic void set_serp_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkScalar m[4]) { 597858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar tempSqrt = SkScalarSqrt(9.f * d[1] * d[1] - 12.f * d[0] * d[2]); 598858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ls = 3.f * d[1] - tempSqrt; 599858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar lt = 6.f * d[0]; 600858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ms = 3.f * d[1] + tempSqrt; 601858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar mt = 6.f * d[0]; 602858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 603858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[0] = ls * ms; 604858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[1] = (3.f * ls * ms - ls * mt - lt * ms) / 3.f; 605858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[2] = (lt * (mt - 2.f * ms) + ls * (3.f * ms - 2.f * mt)) / 3.f; 606858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[3] = (lt - ls) * (mt - ms); 607858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 608858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[0] = ls * ls * ls; 609858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar lt_ls = lt - ls; 610858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[1] = ls * ls * lt_ls * -1.f; 611858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[2] = lt_ls * lt_ls * ls; 612858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[3] = -1.f * lt_ls * lt_ls * lt_ls; 613858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 614858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[0] = ms * ms * ms; 615858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar mt_ms = mt - ms; 616858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[1] = ms * ms * mt_ms * -1.f; 617858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[2] = mt_ms * mt_ms * ms; 618858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[3] = -1.f * mt_ms * mt_ms * mt_ms; 619858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 620858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // If d0 < 0 we need to flip the orientation of our curve 621858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // This is done by negating the k and l values 622858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // We want negative distance values to be on the inside 623858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if ( d[0] > 0) { 624858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org for (int i = 0; i < 4; ++i) { 625858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[i] = -k[i]; 626858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[i] = -l[i]; 627858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 628858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 629858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 630858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 631858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgstatic void set_loop_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkScalar m[4]) { 632858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); 633858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ls = d[1] - tempSqrt; 634858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar lt = 2.f * d[0]; 635858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ms = d[1] + tempSqrt; 636858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar mt = 2.f * d[0]; 637858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 638858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[0] = ls * ms; 639858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[1] = (3.f * ls*ms - ls * mt - lt * ms) / 3.f; 640858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[2] = (lt * (mt - 2.f * ms) + ls * (3.f * ms - 2.f * mt)) / 3.f; 641858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[3] = (lt - ls) * (mt - ms); 642858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 643858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[0] = ls * ls * ms; 644858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[1] = (ls * (ls * (mt - 3.f * ms) + 2.f * lt * ms))/-3.f; 645858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[2] = ((lt - ls) * (ls * (2.f * mt - 3.f * ms) + lt * ms))/3.f; 646858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[3] = -1.f * (lt - ls) * (lt - ls) * (mt - ms); 647858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 648858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[0] = ls * ms * ms; 649858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[1] = (ms * (ls * (2.f * mt - 3.f * ms) + lt * ms))/-3.f; 650858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[2] = ((mt - ms) * (ls * (mt - 3.f * ms) + 2.f * lt * ms))/3.f; 651858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[3] = -1.f * (lt - ls) * (mt - ms) * (mt - ms); 652858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 653858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 654858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // If (d0 < 0 && sign(k1) > 0) || (d0 > 0 && sign(k1) < 0), 655858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // we need to flip the orientation of our curve. 656858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // This is done by negating the k and l values 65707e1c3fd5030869c480c15ff30d36bd161718262commit-bot@chromium.org if ( (d[0] < 0 && k[1] > 0) || (d[0] > 0 && k[1] < 0)) { 658858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org for (int i = 0; i < 4; ++i) { 659858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[i] = -k[i]; 660858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[i] = -l[i]; 661858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 662858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 663858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 664858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 665858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgstatic void set_cusp_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkScalar m[4]) { 666858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar ls = d[2]; 667858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar lt = 3.f * d[1]; 668858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 669858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[0] = ls; 670858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[1] = ls - lt / 3.f; 671858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[2] = ls - 2.f * lt / 3.f; 672858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[3] = ls - lt; 673858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 674858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[0] = ls * ls * ls; 675858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org const SkScalar ls_lt = ls - lt; 676858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[1] = ls * ls * ls_lt; 677858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[2] = ls_lt * ls_lt * ls; 678858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[3] = ls_lt * ls_lt * ls_lt; 679858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 680858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[0] = 1.f; 681858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[1] = 1.f; 682858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[2] = 1.f; 683858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[3] = 1.f; 684858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 685858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 686858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// For the case when a cubic is actually a quadratic 687858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// M = 688858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// 0 0 0 689858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// 1/3 0 1/3 690858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// 2/3 1/3 2/3 691858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org// 1 1 1 692858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgstatic void set_quadratic_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkScalar m[4]) { 693858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[0] = 0.f; 694858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[1] = 1.f/3.f; 695858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[2] = 2.f/3.f; 696858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[3] = 1.f; 697858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 698858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[0] = 0.f; 699858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[1] = 0.f; 700858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[2] = 1.f/3.f; 701858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[3] = 1.f; 702858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 703858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[0] = 0.f; 704858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[1] = 1.f/3.f; 705858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[2] = 2.f/3.f; 706858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org m[3] = 1.f; 707858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 708858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // If d2 < 0 we need to flip the orientation of our curve 709858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // This is done by negating the k and l values 710858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if ( d[2] > 0) { 711858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org for (int i = 0; i < 4; ++i) { 712858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org k[i] = -k[i]; 713858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org l[i] = -l[i]; 714858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 715858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 716858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 717858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 718858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgint GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[10], SkScalar klm[9], 719858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar klm_rev[3]) { 720858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // Variable to store the two parametric values at the loop double point 721858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar smallS = 0.f; 722858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar largeS = 0.f; 723858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 724858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar d[3]; 7258dd31cf69e24ff82865309781107dfab948b6a02caryclark SkCubicType cType = SkClassifyCubic(src, d); 726858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 727858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org int chop_count = 0; 7288dd31cf69e24ff82865309781107dfab948b6a02caryclark if (kLoop_SkCubicType == cType) { 729858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); 730858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ls = d[1] - tempSqrt; 731858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar lt = 2.f * d[0]; 732858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar ms = d[1] + tempSqrt; 733858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar mt = 2.f * d[0]; 734858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org ls = ls / lt; 735858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org ms = ms / mt; 736858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // need to have t values sorted since this is what is expected by SkChopCubicAt 737858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (ls <= ms) { 738858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org smallS = ls; 739858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org largeS = ms; 740858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else { 741858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org smallS = ms; 742858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org largeS = ls; 743858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 744858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 745858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar chop_ts[2]; 746858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (smallS > 0.f && smallS < 1.f) { 747858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org chop_ts[chop_count++] = smallS; 748858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 749858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (largeS > 0.f && largeS < 1.f) { 750858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org chop_ts[chop_count++] = largeS; 751858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 752858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if(dst) { 753858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkChopCubicAt(src, dst, chop_ts, chop_count); 754858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 755858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else { 756858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (dst) { 757858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org memcpy(dst, src, sizeof(SkPoint) * 4); 758858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 759858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 760858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 761858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (klm && klm_rev) { 762858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // Set klm_rev to to match the sub_section of cubic that needs to have its orientation 763858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org // flipped. This will always be the section that is the "loop" 764858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (2 == chop_count) { 765858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[0] = 1.f; 766858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[1] = -1.f; 767858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[2] = 1.f; 768858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else if (1 == chop_count) { 769858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (smallS < 0.f) { 770858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[0] = -1.f; 771858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[1] = 1.f; 772858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else { 773858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[0] = 1.f; 774858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[1] = -1.f; 775858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 776858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else { 777858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org if (smallS < 0.f && largeS > 1.f) { 778858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[0] = -1.f; 779858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } else { 780858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org klm_rev[0] = 1.f; 781858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 782858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 783858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlK[4]; 784858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlL[4]; 785858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlM[4]; 786858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 7878dd31cf69e24ff82865309781107dfab948b6a02caryclark if (kSerpentine_SkCubicType == cType || (kCusp_SkCubicType == cType && 0.f != d[0])) { 788858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_serp_klm(d, controlK, controlL, controlM); 7898dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kLoop_SkCubicType == cType) { 790858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_loop_klm(d, controlK, controlL, controlM); 7918dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kCusp_SkCubicType == cType) { 792858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkASSERT(0.f == d[0]); 793858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_cusp_klm(d, controlK, controlL, controlM); 7948dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kQuadratic_SkCubicType == cType) { 795858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_quadratic_klm(d, controlK, controlL, controlM); 796858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 797858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 798858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org calc_cubic_klm(src, controlK, controlL, controlM, klm, &klm[3], &klm[6]); 799858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 800858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org return chop_count + 1; 801858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 802858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 803858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.orgvoid GrPathUtils::getCubicKLM(const SkPoint p[4], SkScalar klm[9]) { 804858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar d[3]; 8058dd31cf69e24ff82865309781107dfab948b6a02caryclark SkCubicType cType = SkClassifyCubic(p, d); 806858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 807858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlK[4]; 808858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlL[4]; 809858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkScalar controlM[4]; 810858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 8118dd31cf69e24ff82865309781107dfab948b6a02caryclark if (kSerpentine_SkCubicType == cType || (kCusp_SkCubicType == cType && 0.f != d[0])) { 812858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_serp_klm(d, controlK, controlL, controlM); 8138dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kLoop_SkCubicType == cType) { 814858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_loop_klm(d, controlK, controlL, controlM); 8158dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kCusp_SkCubicType == cType) { 816858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org SkASSERT(0.f == d[0]); 817858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_cusp_klm(d, controlK, controlL, controlM); 8188dd31cf69e24ff82865309781107dfab948b6a02caryclark } else if (kQuadratic_SkCubicType == cType) { 819858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org set_quadratic_klm(d, controlK, controlL, controlM); 820858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org } 821858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org 822858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); 823858638d8a5bef8f9940ccec2346a9bcc5f804979commit-bot@chromium.org} 824