GrAAConvexPathRenderer.cpp revision 94b284d719ee5ccd3e2efbd1d7084ec554583bac
169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com/* 369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Copyright 2012 Google Inc. 469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * 569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * found in the LICENSE file. 769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com */ 869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrAAConvexPathRenderer.h" 1069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 1169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrContext.h" 1269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrDrawState.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 1490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrEffect.h" 1569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrPathUtils.h" 1690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrTBackendEffectFactory.h" 1769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkString.h" 185f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h" 1969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkTrace.h" 2069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 2190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLEffect.h" 2290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h" 234647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 2469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comGrAAConvexPathRenderer::GrAAConvexPathRenderer() { 2569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 2669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 2769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comnamespace { 2869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 2969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct Segment { 3069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com enum { 319b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com // These enum values are assumed in member functions below. 329b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kLine = 0, 339b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kQuad = 1, 3469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } fType; 359b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com 369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // line uses one pt, quad uses 2 pts 379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint fPts[2]; 389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // normal to edge ending at each pt 399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec fNorms[2]; 409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // is the corner where the previous segment meets this segment 419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // sharp. If so, fMid is a normalized bisector facing outward. 429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec fMid; 439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int countPoints() { 459b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 469b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fType + 1; 479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endPt() const { 499b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 509b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fPts[fType]; 519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endNorm() const { 539b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 549b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fNorms[fType]; 559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 5669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 5769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 5869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray; 5969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid center_of_mass(const SegmentArray& segments, SkPoint* c) { 6181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar area = 0; 626390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint center = {0, 0}; 639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 646390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint p0 = {0, 0}; 655b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (count > 2) { 665b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // We translate the polygon so that the first point is at the origin. 675b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // This avoids some precision issues with small area polygons far away 685b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // from the origin. 695b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com p0 = segments[0].endPt(); 705b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pi; 715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pj; 72a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // the first and last iteration of the below loop would compute 735b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // zeros since the starting / ending point is (0,0). So instead we start 745b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // at i=1 and make the last iteration i=count-2. 755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pj = segments[1].endPt() - p0; 765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com for (int i = 1; i < count - 1; ++i) { 775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pi = pj; 785b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com const SkPoint pj = segments[i + 1].endPt() - p0; 795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 8081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); 815b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com area += t; 825b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fX += (pi.fX + pj.fX) * t; 835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fY += (pi.fY + pj.fY) * t; 845b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 855b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com } 869aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 87278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // If the poly has no area then we instead return the average of 88278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // its points. 895b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (SkScalarNearlyZero(area)) { 90278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkPoint avg; 91278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.set(0, 0); 92278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com for (int i = 0; i < count; ++i) { 93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com const SkPoint& pt = segments[i].endPt(); 94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fX += pt.fX; 95278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fY += pt.fY; 96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkScalar denom = SK_Scalar1 / count; 98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.scale(denom); 99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com *c = avg; 100278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 101278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com area *= 3; 10281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com area = SkScalarDiv(SK_Scalar1, area); 10381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fX = SkScalarMul(center.fX, area); 10481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fY = SkScalarMul(center.fY, area); 1055b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // undo the translate of p0 to the origin. 1065b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com *c = center + p0; 107278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 108278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com GrAssert(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); 1099aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1119aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid compute_vectors(SegmentArray* segments, 112278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkPoint* fanPt, 113278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkPath::Direction dir, 1149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int* vCount, 1159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int* iCount) { 1169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com center_of_mass(*segments, fanPt); 1179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments->count(); 1189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 119278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // Make the normals point towards the outside 1209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint::Side normSide; 121278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com if (dir == SkPath::kCCW_Direction) { 122278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com normSide = GrPoint::kRight_Side; 123278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 124278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com normSide = GrPoint::kLeft_Side; 125278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 1269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount = 0; 1289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount = 0; 1299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute normals at all points 1309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = (*segments)[a]; 1329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1339aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const GrPoint* prevPt = &sega.endPt(); 1369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int n = segb.countPoints(); 1379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int p = 0; p < n; ++p) { 1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p] = segb.fPts[p] - *prevPt; 1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].normalize(); 1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].setOrthog(segb.fNorms[p], normSide); 1419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com prevPt = &segb.fPts[p]; 1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 5; 1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 9; 1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } else { 1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 6; 1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 12; 1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute mid-vectors where segments meet. TODO: Detect shallow corners 1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // and leave out the wedges and close gaps by stitching segments together. 1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = (*segments)[a]; 1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid = segb.fNorms[0] + sega.endNorm(); 1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid.normalize(); 1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // corner wedges 1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 4; 1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 6; 1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1669732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData { 1679732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData() { fStage = kInitial; } 1689732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com bool isDegenerate() const { return kNonDegenerate != fStage; } 1699732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com enum { 1709732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kInitial, 1719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kPoint, 1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kLine, 1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kNonDegenerate 1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } fStage; 1759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrPoint fFirstPoint; 1769732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrVec fLineNormal; 17781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fLineC; 1789732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}; 1799732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comvoid update_degenerate_test(DegenerateTestData* data, const GrPoint& pt) { 1819732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com static const SkScalar TOL = (SK_Scalar1 / 16); 1829732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com static const SkScalar TOL_SQD = SkScalarMul(TOL, TOL); 1839732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 1849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com switch (data->fStage) { 1859732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kInitial: 1869732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fFirstPoint = pt; 1879732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kPoint; 1889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 1899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kPoint: 1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com if (pt.distanceToSqd(data->fFirstPoint) > TOL_SQD) { 1919732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal = pt - data->fFirstPoint; 1929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.normalize(); 1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.setOrthog(data->fLineNormal); 1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineC = -data->fLineNormal.dot(data->fFirstPoint); 1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kLine; 1969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 1979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kLine: 1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > TOL) { 2009732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kNonDegenerate; 2019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kNonDegenerate: 2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com default: 2059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrCrash("Unexpected degenerate test stage."); 2069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2079732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com} 2089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 209b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.cominline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) { 210a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!path.cheapComputeDirection(dir)) { 211a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 212a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 213af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // check whether m reverses the orientation 214af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com GrAssert(!m.hasPerspective()); 21581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) - 21681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY)); 217af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (det2x2 < 0) { 21830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com *dir = SkPath::OppositeDirection(*dir); 219af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 220a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return true; 221af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com} 222af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 2238d033a1b125886c62906d975b5cc28a382064526bsalomon@google.combool get_segments(const SkPath& path, 224b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix& m, 225af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com SegmentArray* segments, 226af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com SkPoint* fanPt, 227af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com int* vCount, 228af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com int* iCount) { 22969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPath::Iter iter(path, true); 23030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com // This renderer over-emphasizes very thin path regions. We use the distance 2315cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // to the path from the sample to compute coverage. Every pixel intersected 2325cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // by the path will be hit and the maximum distance is sqrt(2)/2. We don't 233fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // notice that the sample may be close to a very thin area of the path and 2345cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // thus should be very light. This is particularly egregious for degenerate 2355cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // line paths. We detect paths that are very close to a line (zero area) and 2365cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // draw nothing. 2379732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData degenerateData; 238a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPath::Direction dir; 239a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // get_direction can fail for some degenerate paths. 240a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!get_direction(path, m, &dir)) { 241a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 242a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 2439732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 24469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com for (;;) { 24569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com GrPoint pts[4]; 24694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com SkPath::Verb verb = iter.next(pts); 24794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 24894b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kMove_Verb: 2491a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 1); 2509732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[0]); 2519732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 25294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: { 253af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com m.mapPoints(pts + 1, 1); 2541a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 25569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->push_back(); 25669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->back().fType = Segment::kLine; 2579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segments->back().fPts[0] = pts[1]; 25869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 25969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 26094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kQuad_Verb: 2611a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts + 1, 2); 2629732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 2639732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 26469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->push_back(); 26569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->back().fType = Segment::kQuad; 2669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segments->back().fPts[0] = pts[1]; 2679aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segments->back().fPts[1] = pts[2]; 26869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 26994b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: { 2701a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 4); 2719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 2729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 2739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[3]); 274af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // unlike quads and lines, the pts[0] will also be read (in 275af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // convertCubicToQuads). 27669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkSTArray<15, SkPoint, true> quads; 277a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); 27869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com int count = quads.count(); 27969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com for (int q = 0; q < count; q += 3) { 28069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->push_back(); 28169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com segments->back().fType = Segment::kQuad; 2829aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segments->back().fPts[0] = quads[q + 1]; 2839aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segments->back().fPts[1] = quads[q + 2]; 28469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 28569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 28669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com }; 28794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 2889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com if (degenerateData.isDegenerate()) { 2899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return false; 2909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } else { 291278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com compute_vectors(segments, fanPt, dir, vCount, iCount); 2929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return true; 2939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 29469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com default: 29569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 29669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 29769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 29869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 29969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 30069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex { 30169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com GrPoint fPos; 3029aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint fUV; 30381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD0; 30481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD1; 30569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 306fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3079aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.comvoid create_vertices(const SegmentArray& segments, 3089aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& fanPt, 3099aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com QuadVertex* verts, 3109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com uint16_t* idxs) { 31169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com int v = 0; 31269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com int i = 0; 31369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 3159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 3169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = segments[a]; 3179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 3189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& segb = segments[b]; 319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // FIXME: These tris are inset in the 1 unit arc around the corner 3219aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fPos = sega.endPt(); 3229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fPos = verts[v + 0].fPos + sega.endNorm(); 3239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fPos = verts[v + 0].fPos + segb.fMid; 3249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fPos = verts[v + 0].fPos + segb.fNorms[0]; 3259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fUV.set(0,0); 3269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fUV.set(0,-SK_Scalar1); 3279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fUV.set(0,-SK_Scalar1); 3289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fUV.set(0,-SK_Scalar1); 3299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1; 3309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1; 3319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1; 3329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1; 333fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 33469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com idxs[i + 0] = v + 0; 3359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 1] = v + 2; 3369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 2] = v + 1; 33769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com idxs[i + 3] = v + 0; 3389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 4] = v + 3; 3399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 5] = v + 2; 340fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 34169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com v += 4; 34269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com i += 6; 34369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 34569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com verts[v + 0].fPos = fanPt; 3469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fPos = sega.endPt(); 3479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fPos = segb.fPts[0]; 3489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fPos = verts[v + 1].fPos + segb.fNorms[0]; 3509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 4].fPos = verts[v + 2].fPos + segb.fNorms[0]; 3519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // we draw the line edge as a degenerate quad (u is 0, v is the 3539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // signed distance to the edge) 35481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dist = fanPt.distanceToLineBetween(verts[v + 1].fPos, 3559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fPos); 3569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fUV.set(0, dist); 3579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fUV.set(0, 0); 3589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fUV.set(0, 0); 3599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fUV.set(0, -SK_Scalar1); 3609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 4].fUV.set(0, -SK_Scalar1); 3619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fD0 = verts[v + 0].fD1 = -SK_Scalar1; 3639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fD0 = verts[v + 1].fD1 = -SK_Scalar1; 3649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fD0 = verts[v + 2].fD1 = -SK_Scalar1; 3659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fD0 = verts[v + 3].fD1 = -SK_Scalar1; 3669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 4].fD0 = verts[v + 4].fD1 = -SK_Scalar1; 36769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 36869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com idxs[i + 0] = v + 0; 3699aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 1] = v + 2; 3709aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 2] = v + 1; 3719aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3729aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 3] = v + 3; 3739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 4] = v + 1; 3749aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 5] = v + 2; 3759aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3769aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 6] = v + 4; 3779aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 7] = v + 3; 378068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com idxs[i + 8] = v + 2; 379495e210eb1b66d8a8fc3f46ca1def3c78c724a38bsalomon@google.com 380068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com v += 5; 3819aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com i += 9; 382068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com } else { 3839aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]}; 3849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3859aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec midVec = segb.fNorms[0] + segb.fNorms[1]; 3869aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com midVec.normalize(); 3879aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3889aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fPos = fanPt; 3899aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fPos = qpts[0]; 3909aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fPos = qpts[2]; 3919aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 3].fPos = qpts[0] + segb.fNorms[0]; 3929aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 4].fPos = qpts[2] + segb.fNorms[1]; 3939aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 5].fPos = qpts[1] + midVec; 3949aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 39581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar c = segb.fNorms[0].dot(qpts[0]); 3969aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; 3979aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fD0 = 0.f; 3989aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; 39981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 3].fD0 = -SK_ScalarMax/100; 40081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 4].fD0 = -SK_ScalarMax/100; 40181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 5].fD0 = -SK_ScalarMax/100; 4029aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4039aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com c = segb.fNorms[1].dot(qpts[2]); 4049aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; 4059aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; 4069aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com verts[v + 2].fD1 = 0.f; 40781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 3].fD1 = -SK_ScalarMax/100; 40881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 4].fD1 = -SK_ScalarMax/100; 40981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com verts[v + 5].fD1 = -SK_ScalarMax/100; 4109aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4111971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix toUV(qpts); 4121971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + v); 4139aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 0] = v + 3; 4159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 1] = v + 1; 4169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 2] = v + 2; 4179aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 3] = v + 4; 4189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 4] = v + 3; 4199aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 5] = v + 2; 4209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4219aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 6] = v + 5; 4229aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 7] = v + 3; 4239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 8] = v + 4; 4249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 9] = v + 0; 4269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 10] = v + 2; 4279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com idxs[i + 11] = v + 1; 4289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com v += 6; 4309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com i += 12; 43169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 43269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 43369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 43469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 43569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 43669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 43790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 43890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 43990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/* 44090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 44190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed 44290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in 44390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated 44490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to 445041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad. 446041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support. 44790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 44890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 44990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass QuadEdgeEffect : public GrEffect { 45090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 45190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 45290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 453d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gQuadEdgeEffect, QuadEdgeEffect, ()); 454d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gQuadEdgeEffect->ref(); 455d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gQuadEdgeEffect; 45690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 45790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 45890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~QuadEdgeEffect() {} 45990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 46090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "QuadEdge"; } 46190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 462041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 46390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 46490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 46590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 46690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 46790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 46890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<QuadEdgeEffect>::getInstance(); 46990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 47090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 47190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 47290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 47390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 47490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 47590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 47690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 47790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 47890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 47990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 48090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 48190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 48290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 48390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 48490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 48590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 48690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 48790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkAssertResult(builder->enableFeature( 48890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 48990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); 49090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 49190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // keep the derivative instructions outside the conditional 49290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 49390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 49490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 49590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // today we know z and w are in device space. We could use derivatives 49690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, 49790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 49890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf ("\t\t} else {\n"); 49990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 50090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "\t\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 50190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName, fsName); 50290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 50390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 50490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = " 50590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n"); 50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 508018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 51090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 51290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 52190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 52290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 523041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com 52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 525041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com QuadEdgeEffect() { 526041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 53690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(QuadEdgeEffect); 53990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* QuadEdgeEffect::TestCreate(SkMWCRandom* random, 54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 54390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 54490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // Doesn't work without derivative instructions. 54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL; 54690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 54990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 5508a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAConvexPathRenderer::canDrawPath(const SkPath& path, 5515f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 5528a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 5538a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 554bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com return (target->caps()->shaderDerivativeSupport() && antiAlias && 5555f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()); 556c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 557c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 558429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace { 559429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 560429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge 561429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPathAttribs[] = { 562429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 563429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 564429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 565429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 566429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 567429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 568c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, 5695f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 570c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 571c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 572c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 573af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com const SkPath* path = &origPath; 574af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (path->isEmpty()) { 575c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 57669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 5774647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 5784647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 579c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawState* drawState = target->drawState(); 58069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 581a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com GrDrawState::AutoDeviceCoordDraw adcd(drawState); 582a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!adcd.succeeded()) { 583e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 58469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 585b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* vm = &adcd.getOriginalMatrix(); 58669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 587af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // We use the fact that SkPath::transform path does subdivision based on 588af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // perspective. Otherwise, we apply the view matrix when copying to the 589af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // segment representation. 590af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com SkPath tmpPath; 591a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (vm->hasPerspective()) { 592a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com origPath.transform(*vm, &tmpPath); 593af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com path = &tmpPath; 594b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com vm = &SkMatrix::I(); 595af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 596af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 59769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com QuadVertex *verts; 59869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com uint16_t* idxs; 59969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6009aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int vCount; 6019aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int iCount; 60268a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com enum { 60368a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com kPreallocSegmentCnt = 512 / sizeof(Segment), 60468a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com }; 60568a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com SkSTArray<kPreallocSegmentCnt, Segment, true> segments; 6069aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com SkPoint fanPt; 607af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 608a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!get_segments(*path, *vm, &segments, &fanPt, &vCount, &iCount)) { 609c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 61069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 61169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 612429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs)); 6134647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 6144647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com enum { 6154647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // the edge effects share this stage with glyph rendering 6164647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kGlyphMaskStage in GrTextContext) && SW path rendering 6174647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kPathMaskStage in GrSWMaskHelper) 6184647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com kEdgeEffectStage = GrPaint::kTotalStages, 6194647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com }; 6204647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com static const int kEdgeAttrIndex = 1; 62190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* quadEffect = QuadEdgeEffect::Create(); 6224647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, quadEffect, kEdgeAttrIndex)->unref(); 6234647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 624b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount); 625b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com if (!arg.succeeded()) { 626c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 62769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 6289b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrAssert(sizeof(QuadVertex) == drawState->getVertexSize()); 629b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com verts = reinterpret_cast<QuadVertex*>(arg.vertices()); 630b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com idxs = reinterpret_cast<uint16_t*>(arg.indices()); 63169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com create_vertices(segments, fanPt, verts, idxs); 63369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 63447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 635c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // start vertex 636c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // start index 637c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com vCount, 638c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com iCount); 639a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 640c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 64169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 642