GrAAConvexPathRenderer.cpp revision 515dcd36032997ce335daa0163c6d67e851bcad1
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.comstruct Segment { 2869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com enum { 299b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com // These enum values are assumed in member functions below. 309b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kLine = 0, 319b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kQuad = 1, 3269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } fType; 339b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com 349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // line uses one pt, quad uses 2 pts 359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint fPts[2]; 369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // normal to edge ending at each pt 379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec fNorms[2]; 389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // is the corner where the previous segment meets this segment 399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // sharp. If so, fMid is a normalized bisector facing outward. 409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec fMid; 419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int countPoints() { 439b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 449b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fType + 1; 459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endPt() const { 479b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 489b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fPts[fType]; 499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endNorm() const { 519b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 529b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fNorms[fType]; 539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 5469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 5569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 5669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray; 5769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 58fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void center_of_mass(const SegmentArray& segments, SkPoint* c) { 5981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar area = 0; 606390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint center = {0, 0}; 619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 626390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint p0 = {0, 0}; 635b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (count > 2) { 645b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // We translate the polygon so that the first point is at the origin. 655b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // This avoids some precision issues with small area polygons far away 665b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // from the origin. 675b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com p0 = segments[0].endPt(); 685b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pi; 695b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pj; 70a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // the first and last iteration of the below loop would compute 715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // zeros since the starting / ending point is (0,0). So instead we start 725b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // at i=1 and make the last iteration i=count-2. 735b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pj = segments[1].endPt() - p0; 745b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com for (int i = 1; i < count - 1; ++i) { 755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pi = pj; 765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com const SkPoint pj = segments[i + 1].endPt() - p0; 775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 7881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); 795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com area += t; 805b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fX += (pi.fX + pj.fX) * t; 815b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fY += (pi.fY + pj.fY) * t; 825b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com } 849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 85278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // If the poly has no area then we instead return the average of 86278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // its points. 875b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (SkScalarNearlyZero(area)) { 88278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkPoint avg; 89278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.set(0, 0); 90278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com for (int i = 0; i < count; ++i) { 91278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com const SkPoint& pt = segments[i].endPt(); 92278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fX += pt.fX; 93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fY += pt.fY; 94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 95278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkScalar denom = SK_Scalar1 / count; 96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.scale(denom); 97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com *c = avg; 98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com area *= 3; 10081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com area = SkScalarDiv(SK_Scalar1, area); 10181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fX = SkScalarMul(center.fX, area); 10281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fY = SkScalarMul(center.fY, area); 1035b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // undo the translate of p0 to the origin. 1045b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com *c = center + p0; 105278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 106f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); 1079aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1089aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 109fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void compute_vectors(SegmentArray* segments, 110fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPoint* fanPt, 111fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPath::Direction dir, 112fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* vCount, 113fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* iCount) { 1149aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com center_of_mass(*segments, fanPt); 1159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments->count(); 1169aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 117278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // Make the normals point towards the outside 1189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint::Side normSide; 119278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com if (dir == SkPath::kCCW_Direction) { 120278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com normSide = GrPoint::kRight_Side; 121278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 122278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com normSide = GrPoint::kLeft_Side; 123278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 1249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount = 0; 1269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount = 0; 1279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute normals at all points 1289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1297d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Segment& sega = (*segments)[a]; 1309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1339aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const GrPoint* prevPt = &sega.endPt(); 1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int n = segb.countPoints(); 1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int p = 0; p < n; ++p) { 1369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p] = segb.fPts[p] - *prevPt; 1379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].normalize(); 1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].setOrthog(segb.fNorms[p], normSide); 1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com prevPt = &segb.fPts[p]; 1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 5; 1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 9; 1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } else { 1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 6; 1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 12; 1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute mid-vectors where segments meet. TODO: Detect shallow corners 1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // and leave out the wedges and close gaps by stitching segments together. 1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = (*segments)[a]; 1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid = segb.fNorms[0] + sega.endNorm(); 1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid.normalize(); 1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // corner wedges 1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 4; 1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 6; 1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1649732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData { 1659732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData() { fStage = kInitial; } 1669732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com bool isDegenerate() const { return kNonDegenerate != fStage; } 1679732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com enum { 1689732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kInitial, 1699732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kPoint, 1709732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kLine, 1719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kNonDegenerate 1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } fStage; 1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrPoint fFirstPoint; 1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrVec fLineNormal; 17581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fLineC; 1769732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}; 1779732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 178fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kClose = (SK_Scalar1 / 16); 179fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kCloseSqd = SkScalarMul(kClose, kClose); 1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 181fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void update_degenerate_test(DegenerateTestData* data, const GrPoint& pt) { 1829732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com switch (data->fStage) { 1839732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kInitial: 1849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fFirstPoint = pt; 1859732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kPoint; 1869732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 1879732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kPoint: 188fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pt.distanceToSqd(data->fFirstPoint) > kCloseSqd) { 1899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal = pt - data->fFirstPoint; 1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.normalize(); 1919732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.setOrthog(data->fLineNormal); 1929732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineC = -data->fLineNormal.dot(data->fFirstPoint); 1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kLine; 1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 1969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kLine: 197fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) { 1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kNonDegenerate; 1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2009732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kNonDegenerate: 2019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com default: 2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com GrCrash("Unexpected degenerate test stage."); 2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com} 2069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 207fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) { 208a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!path.cheapComputeDirection(dir)) { 209a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 210a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 211af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // check whether m reverses the orientation 212f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!m.hasPerspective()); 21381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) - 21481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY)); 215af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (det2x2 < 0) { 21630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com *dir = SkPath::OppositeDirection(*dir); 217af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 218a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return true; 219af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com} 220af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 221fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_line_to_segment(const SkPoint& pt, SegmentArray* segments) { 222fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->push_back(); 223fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fType = Segment::kLine; 224fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[0] = pt; 225fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 226fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 227fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_quad_segment(const SkPoint pts[3], SegmentArray* segments) { 228fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || pts[1].distanceToSqd(pts[2]) < kCloseSqd) { 229fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pts[0] != pts[2]) { 230fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org add_line_to_segment(pts[2], segments); 231fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 232fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } else { 233fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->push_back(); 234fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fType = Segment::kQuad; 235fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[0] = pts[1]; 236fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[1] = pts[2]; 237fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 238fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 239fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 240fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_cubic_segments(const SkPoint pts[4], 241fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPath::Direction dir, 242fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SegmentArray* segments) { 243fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkSTArray<15, SkPoint, true> quads; 244fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); 245fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int count = quads.count(); 246fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org for (int q = 0; q < count; q += 3) { 247fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org add_quad_segment(&quads[q], segments); 248fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 249fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 250fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 251fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic bool get_segments(const SkPath& path, 252fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org const SkMatrix& m, 253fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SegmentArray* segments, 254fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPoint* fanPt, 255fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* vCount, 256fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* iCount) { 25769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPath::Iter iter(path, true); 25830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com // This renderer over-emphasizes very thin path regions. We use the distance 2595cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // to the path from the sample to compute coverage. Every pixel intersected 2605cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // by the path will be hit and the maximum distance is sqrt(2)/2. We don't 261fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // notice that the sample may be close to a very thin area of the path and 2625cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // thus should be very light. This is particularly egregious for degenerate 2635cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // line paths. We detect paths that are very close to a line (zero area) and 2645cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // draw nothing. 2659732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData degenerateData; 266a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPath::Direction dir; 267a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // get_direction can fail for some degenerate paths. 268a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!get_direction(path, m, &dir)) { 269a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 270a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 2719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 27269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com for (;;) { 27369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com GrPoint pts[4]; 27494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com SkPath::Verb verb = iter.next(pts); 27594b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 27694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kMove_Verb: 2771a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 1); 2789732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[0]); 2799732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 28094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: { 281fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org m.mapPoints(&pts[1], 1); 2821a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 283fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org add_line_to_segment(pts[1], segments); 28469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 28569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 28694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kQuad_Verb: 287fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org m.mapPoints(pts, 3); 2889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 2899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 290fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org add_quad_segment(pts, segments); 29169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 29294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: { 2931a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 4); 2949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 2959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 2969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[3]); 297fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org add_cubic_segments(pts, dir, segments); 29869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 29969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com }; 30094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 3019732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com if (degenerateData.isDegenerate()) { 3029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return false; 3039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } else { 304278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com compute_vectors(segments, fanPt, dir, vCount, iCount); 3059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return true; 3069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 30769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com default: 30869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 30969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 31069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 31169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 31269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 31369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex { 31469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com GrPoint fPos; 3159aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint fUV; 31681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD0; 31781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD1; 31869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3207d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comstruct Draw { 3217d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Draw() : fVertexCnt(0), fIndexCnt(0) {} 3227d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int fVertexCnt; 3237d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int fIndexCnt; 3247d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com}; 3257d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3267d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comtypedef SkTArray<Draw, true> DrawArray; 3277d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 328fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void create_vertices(const SegmentArray& segments, 329fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org const SkPoint& fanPt, 330fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org DrawArray* draws, 331fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org QuadVertex* verts, 332fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org uint16_t* idxs) { 3337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Draw* draw = &draws->push_back(); 3347d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // alias just to make vert/index assignments easier to read. 3357d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int* v = &draw->fVertexCnt; 3367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int* i = &draw->fIndexCnt; 33769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 3399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 3409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = segments[a]; 3419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 3429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& segb = segments[b]; 343fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3447d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // Check whether adding the verts for this segment to the current draw would cause index 3457d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // values to overflow. 3467d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int vCount = 4; 3477d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com if (Segment::kLine == segb.fType) { 3487d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vCount += 5; 3497d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } else { 3507d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vCount += 6; 3517d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 3527d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com if (draw->fVertexCnt + vCount > (1 << 16)) { 3537d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts += *v; 3547d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs += *i; 3557d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com draw = &draws->push_back(); 3567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com v = &draw->fVertexCnt; 3577d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com i = &draw->fIndexCnt; 3587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 3597d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // FIXME: These tris are inset in the 1 unit arc around the corner 3617d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = sega.endPt(); 3627d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm(); 3637d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid; 3647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0]; 3657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fUV.set(0,0); 3667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fUV.set(0,-SK_Scalar1); 3677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fUV.set(0,-SK_Scalar1); 3687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fUV.set(0,-SK_Scalar1); 3697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; 3707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; 3717d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; 3727d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; 3737d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3747d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 0; 3757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 2; 3767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 1; 3777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 0; 3787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 3; 3797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 3807d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 4; 3827d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 6; 38369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 3857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = fanPt; 3867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = sega.endPt(); 3877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = segb.fPts[0]; 3889aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0]; 3907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0]; 3919aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 3929aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // we draw the line edge as a degenerate quad (u is 0, v is the 3939aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // signed distance to the edge) 3947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos, 3957d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos); 3967d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fUV.set(0, dist); 3977d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fUV.set(0, 0); 3987d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fUV.set(0, 0); 3997d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fUV.set(0, -SK_Scalar1); 4007d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fUV.set(0, -SK_Scalar1); 4017d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4027d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; 4037d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; 4047d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; 4057d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; 4067d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1; 4077d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4087d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 0; 4097d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 2; 4107d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 1; 4117d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4127d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 3; 4137d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 1; 4147d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 4157d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4167d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 6] = *v + 4; 4177d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 7] = *v + 3; 4187d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 8] = *v + 2; 4197d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4207d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 5; 4217d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 9; 422068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com } else { 4239aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]}; 4249aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4259aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com GrVec midVec = segb.fNorms[0] + segb.fNorms[1]; 4269aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com midVec.normalize(); 4279aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4287d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = fanPt; 4297d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = qpts[0]; 4307d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = qpts[2]; 4317d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = qpts[0] + segb.fNorms[0]; 4327d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fPos = qpts[2] + segb.fNorms[1]; 4337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fPos = qpts[1] + midVec; 4349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 43581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar c = segb.fNorms[0].dot(qpts[0]); 4367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; 4377d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = 0.f; 4387d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; 4397d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = -SK_ScalarMax/100; 4407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD0 = -SK_ScalarMax/100; 4417d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fD0 = -SK_ScalarMax/100; 4429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com c = segb.fNorms[1].dot(qpts[2]); 4447d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; 4457d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; 4467d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD1 = 0.f; 4477d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD1 = -SK_ScalarMax/100; 4487d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD1 = -SK_ScalarMax/100; 4497d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fD1 = -SK_ScalarMax/100; 4509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4511971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix toUV(qpts); 4527d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + *v); 4539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4547d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 3; 4557d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 1; 4567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 2; 4577d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 4; 4587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 3; 4597d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 4609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4617d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 6] = *v + 5; 4627d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 7] = *v + 3; 4637d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 8] = *v + 4; 4649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 9] = *v + 0; 4667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 10] = *v + 2; 4677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 11] = *v + 1; 4689aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 6; 4707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 12; 47169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 47269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 47369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 47469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 47590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 47690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 47790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/* 47890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 47990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed 48090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in 48190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated 48290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to 483041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad. 484041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support. 48590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 48690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 48790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass QuadEdgeEffect : public GrEffect { 48890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 48990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 49090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 491d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gQuadEdgeEffect, QuadEdgeEffect, ()); 492d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gQuadEdgeEffect->ref(); 493d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gQuadEdgeEffect; 49490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 49590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 49690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~QuadEdgeEffect() {} 49790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 49890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "QuadEdge"; } 49990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 500041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 50190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 50290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 50390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 50490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 50590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<QuadEdgeEffect>::getInstance(); 50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 50890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 51090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 51190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 51290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 52190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 52290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 52390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkAssertResult(builder->enableFeature( 52690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); 52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // keep the derivative instructions outside the conditional 53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // today we know z and w are in device space. We could use derivatives 53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, 53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 53690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf ("\t\t} else {\n"); 53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 53890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "\t\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 53990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName, fsName); 54090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tedgeAlpha = " 54390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n"); 54490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 546018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 54890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 55090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 55190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 55390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 55490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 55590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 55790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 55990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 56090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 561041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com 56290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 563041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com QuadEdgeEffect() { 564041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 56590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 56690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 56790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 56890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 56990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 57090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 57290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 57490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 57590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(QuadEdgeEffect); 57790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* QuadEdgeEffect::TestCreate(SkMWCRandom* random, 57990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 58090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 58190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 58290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // Doesn't work without derivative instructions. 58390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL; 58490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 58590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 58790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 5888a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAConvexPathRenderer::canDrawPath(const SkPath& path, 5895f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 5908a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 5918a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 592bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com return (target->caps()->shaderDerivativeSupport() && antiAlias && 5935f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()); 594c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 595c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 596429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace { 597429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 598429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge 599429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPathAttribs[] = { 600429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 601429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 602429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 603429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 604429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 605429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 606c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, 6075f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 608c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 609c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 610c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 611af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com const SkPath* path = &origPath; 612af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (path->isEmpty()) { 613c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 61469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 6154647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 616137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix viewMatrix = target->getDrawState().getViewMatrix(); 617137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawTarget::AutoStateRestore asr; 618137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 619e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 62069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 621137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawState* drawState = target->drawState(); 62269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 623af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // We use the fact that SkPath::transform path does subdivision based on 624af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // perspective. Otherwise, we apply the view matrix when copying to the 625af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // segment representation. 626af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com SkPath tmpPath; 627137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (viewMatrix.hasPerspective()) { 628137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com origPath.transform(viewMatrix, &tmpPath); 629af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com path = &tmpPath; 630137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com viewMatrix = SkMatrix::I(); 631af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 632af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 63369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com QuadVertex *verts; 63469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com uint16_t* idxs; 63569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int vCount; 6379aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int iCount; 63868a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com enum { 63968a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com kPreallocSegmentCnt = 512 / sizeof(Segment), 6407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com kPreallocDrawCnt = 4, 64168a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com }; 64268a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com SkSTArray<kPreallocSegmentCnt, Segment, true> segments; 6439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com SkPoint fanPt; 644af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 645137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount)) { 646c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 64769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 64869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 649429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs)); 6504647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 6514647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com static const int kEdgeAttrIndex = 1; 65290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* quadEffect = QuadEdgeEffect::Create(); 653eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com drawState->addCoverageEffect(quadEffect, kEdgeAttrIndex)->unref(); 6544647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 655b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount); 656b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com if (!arg.succeeded()) { 657c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 65869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 659f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(sizeof(QuadVertex) == drawState->getVertexSize()); 660b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com verts = reinterpret_cast<QuadVertex*>(arg.vertices()); 661b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com idxs = reinterpret_cast<uint16_t*>(arg.indices()); 66269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6637d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com SkSTArray<kPreallocDrawCnt, Draw, true> draws; 6647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com create_vertices(segments, fanPt, &draws, verts, idxs); 6657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 6661dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // This is valid because all the computed verts are within 1 pixel of the path control points. 6671dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect devBounds; 668137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com devBounds = path->getBounds(); 669137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com viewMatrix.mapRect(&devBounds); 6701dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com devBounds.outset(SK_Scalar1, SK_Scalar1); 6711dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 6721dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // Check devBounds 673515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG 6741dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect tolDevBounds = devBounds; 6751dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); 6761dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect actualBounds; 6771dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.set(verts[0].fPos, verts[1].fPos); 6781dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com for (int i = 2; i < vCount; ++i) { 6791dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.growToInclude(verts[i].fPos.fX, verts[i].fPos.fY); 6801dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 681f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(tolDevBounds.contains(actualBounds)); 6821dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com#endif 6831dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 6847d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int vOffset = 0; 6857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com for (int i = 0; i < draws.count(); ++i) { 6867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com const Draw& draw = draws[i]; 6877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 6887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vOffset, // start vertex 6897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 0, // start index 6907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com draw.fVertexCnt, 6911dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com draw.fIndexCnt, 6921dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &devBounds); 6937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vOffset += draw.fVertexCnt; 6947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 695a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 696c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 69769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 698