EdgeWalker.cpp revision fb173424e915e696a73067d616ce4f39a407261a
1c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 2c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com/* 3c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * Copyright 2012 Google Inc. 4c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * 5c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 6c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * found in the LICENSE file. 7c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com */ 8c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 96680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com#include "CurveIntersection.h" 10a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com#include "Intersections.h" 11c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "LineIntersection.h" 12c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "SkPath.h" 13c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "SkRect.h" 14c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "SkTArray.h" 15c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "SkTDArray.h" 16d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#include "ShapeOps.h" 17c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com#include "TSearch.h" 18c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 19fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if 01 // set to 1 for no debugging whatsoever 20d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.comconst bool gShowDebugf = false; // FIXME: remove once debugging is complete 212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_DUMP 0 232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD 0 242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_INTERSECTING_TS 0 252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_BOTTOM_TS 0 262e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ABOVE_BELOW 0 272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ACTIVE_LESS_THAN 0 28fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_ASSEMBLE 0 29fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_BRIDGE 0 302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_SORT_HORIZONTAL 0 312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT 0 322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT_LESS_THAN 0 332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADJUST_COINCIDENT 0 34752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#define DEBUG_BOTTOM 0 35198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#define DEBUG_SPLIT 0 36fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_STITCH_EDGE 0 372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#else 38d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.comconst bool gShowDebugf = true; // FIXME: remove once debugging is complete 392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_DUMP 01 412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD 01 422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_INTERSECTING_TS 0 432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_BOTTOM_TS 0 442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ABOVE_BELOW 01 45a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com#define DEBUG_ACTIVE_LESS_THAN 0 46fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_ASSEMBLE 1 47fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_BRIDGE 1 482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_SORT_HORIZONTAL 01 492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT 01 502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT_LESS_THAN 0 512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADJUST_COINCIDENT 1 52198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#define DEBUG_BOTTOM 0 53198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#define DEBUG_SPLIT 1 54fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_STITCH_EDGE 1 55752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 58fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE || DEBUG_BRIDGE 59fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic const char* kLVerbStr[] = {"", "line", "quad", "cubic"}; 60fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 61fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 62fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"}; 63fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 64fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 656680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic int LineIntersect(const SkPoint a[2], const SkPoint b[2], 66a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 67a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 68a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 69a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return intersect(aLine, bLine, intersections.fT[0], intersections.fT[1]); 70a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 71a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 72a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2], 73a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 74a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 75a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 76198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intersect(aQuad, bLine, intersections); 77198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 78a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 79a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 80a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int CubicLineIntersect(const SkPoint a[2], const SkPoint b[3], 81a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 82a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 83a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 84a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 85198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersect(aCubic, bLine, intersections.fT[0], intersections.fT[1]); 86a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 87a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 88a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int QuadIntersect(const SkPoint a[3], const SkPoint b[3], 89a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 90a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 91a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic bQuad = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}}; 92198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intersect(aQuad, bQuad, intersections); 93198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 94a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 95a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 96a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int CubicIntersect(const SkPoint a[4], const SkPoint b[4], 97a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 98a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 99a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 100a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic bCubic = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}, 101a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {b[3].fX, b[3].fY}}; 102198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intersect(aCubic, bCubic, intersections); 103198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 104c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 105c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic int LineIntersect(const SkPoint a[2], SkScalar left, SkScalar right, 1072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y, double aRange[2]) { 108a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return horizontalLineIntersect(aLine, left, right, y, aRange); 110c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 111c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 112198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic int QuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right, 113198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y, double aRange[3]) { 114198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 115198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return horizontalIntersect(aQuad, left, right, y, aRange); 116198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 117198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 118198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic int CubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right, 119198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y, double aRange[4]) { 120198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 121198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com {a[3].fX, a[3].fY}}; 122198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return horizontalIntersect(aCubic, left, right, y, aRange); 123198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 124198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 125cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.comstatic void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) { 126a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line line = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 127cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com double x, y; 128a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(line, t, x, y); 129cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com out->fX = SkDoubleToScalar(x); 130cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com out->fY = SkDoubleToScalar(y); 131cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com} 132cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com 133a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) { 134a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 135a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double x, y; 136a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(quad, t, x, y); 137a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fX = SkDoubleToScalar(x); 138a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fY = SkDoubleToScalar(y); 1392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 141a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) { 142a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 143a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 144a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double x, y; 145a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(cubic, t, x, y); 146a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fX = SkDoubleToScalar(x); 147a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fY = SkDoubleToScalar(y); 1482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1506680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic SkScalar LineYAtT(const SkPoint a[2], double t) { 151a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1526680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com double y; 1536680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com xy_at_t(aLine, t, *(double*) 0, y); 1546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return SkDoubleToScalar(y); 1556680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 1566680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 157a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic SkScalar QuadYAtT(const SkPoint a[3], double t) { 158a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 159a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double y; 160a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(quad, t, *(double*) 0, y); 161a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return SkDoubleToScalar(y); 162a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 163a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 164a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic SkScalar CubicYAtT(const SkPoint a[4], double t) { 165a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 166a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 167a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double y; 168a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(cubic, t, *(double*) 0, y); 169a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return SkDoubleToScalar(y); 170a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 171a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 1726680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic void LineSubDivide(const SkPoint a[2], double startT, double endT, 1736680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkPoint sub[2]) { 174a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1756680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com _Line dst; 1766680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub_divide(aLine, startT, endT, dst); 1776680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 1786680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 1796680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 1806680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 1816680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 1826680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 183a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void QuadSubDivide(const SkPoint a[3], double startT, double endT, 184a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint sub[3]) { 185a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 186a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Quadratic dst; 187a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub_divide(aQuad, startT, endT, dst); 188a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 189a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 190a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 191a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 192a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fX = SkDoubleToScalar(dst[2].x); 193a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fY = SkDoubleToScalar(dst[2].y); 1942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1956680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 196a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void CubicSubDivide(const SkPoint a[4], double startT, double endT, 197a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint sub[4]) { 198a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 199a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 200a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Cubic dst; 201a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub_divide(aCubic, startT, endT, dst); 202a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 203a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 204a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 205a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 206a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fX = SkDoubleToScalar(dst[2].x); 207a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fY = SkDoubleToScalar(dst[2].y); 208a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[3].fX = SkDoubleToScalar(dst[3].x); 209a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[3].fY = SkDoubleToScalar(dst[3].y); 210a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 211fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 212fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic void QuadSubBounds(const SkPoint a[3], double startT, double endT, 213fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkRect& bounds) { 214fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint dst[3]; 215fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com QuadSubDivide(a, startT, endT, dst); 216fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fLeft = bounds.fRight = dst[0].fX; 217fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fTop = bounds.fBottom = dst[0].fY; 218fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 1; index < 3; ++index) { 219fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.growToInclude(dst[index].fX, dst[index].fY); 220fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 221fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com} 222fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 223fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic void CubicSubBounds(const SkPoint a[4], double startT, double endT, 224fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkRect& bounds) { 225fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint dst[4]; 226fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com CubicSubDivide(a, startT, endT, dst); 227fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fLeft = bounds.fRight = dst[0].fX; 228fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fTop = bounds.fBottom = dst[0].fY; 229fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 1; index < 4; ++index) { 230fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.growToInclude(dst[index].fX, dst[index].fY); 231fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 232fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com} 233fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 234c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com/* 235c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comlist of edges 236c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.combounds for edge 237c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comsort 238c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comactive T 239c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 240c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comif a contour's bounds is outside of the active area, no need to create edges 241c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com*/ 242c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 243c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com/* given one or more paths, 244c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com find the bounds of each contour, select the active contours 245c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for each active contour, compute a set of edges 246c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com each edge corresponds to one or more lines and curves 247c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com leave edges unbroken as long as possible 248c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com when breaking edges, compute the t at the break but leave the control points alone 249c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 250c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com */ 251c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 252c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid contourBounds(const SkPath& path, SkTDArray<SkRect>& boundsArray) { 253c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Iter iter(path, false); 254c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint pts[4]; 255c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb verb; 256c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkRect bounds; 257c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.setEmpty(); 258c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int count = 0; 259c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 260c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com switch (verb) { 261c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kMove_Verb: 262c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (!bounds.isEmpty()) { 263c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *boundsArray.append() = bounds; 264c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 265c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY); 266c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 0; 267c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 268c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kLine_Verb: 269c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 1; 270c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 271c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kQuad_Verb: 272c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 2; 273c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 274c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kCubic_Verb: 275c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 3; 276c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 277c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kClose_Verb: 278c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 0; 279c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 280c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com default: 281c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkDEBUGFAIL("bad verb"); 282c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 283c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 284c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (int i = 1; i <= count; ++i) { 285c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.growToInclude(pts[i].fX, pts[i].fY); 286c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 287c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 288c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 289c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 290f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic bool extendLine(const SkPoint line[2], const SkPoint& add) { 291f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // FIXME: allow this to extend lines that have slopes that are nearly equal 292f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dx1 = line[1].fX - line[0].fX; 293f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dy1 = line[1].fY - line[0].fY; 294f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dx2 = add.fX - line[0].fX; 295f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dy2 = add.fY - line[0].fY; 296f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return dx1 * dy2 == dx2 * dy1; 297f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2986680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 2992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZATION: this should point to a list of input data rather than duplicating 3002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// the line data here. This would reduce the need to assemble the results. 301f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstruct OutEdge { 302f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com bool operator<(const OutEdge& rh) const { 303cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& first = fPts[0]; 304cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& rhFirst = rh.fPts[0]; 305f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return first.fY == rhFirst.fY 306f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ? first.fX < rhFirst.fX 307f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com : first.fY < rhFirst.fY; 308f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 309752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 310cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkPoint fPts[4]; 3112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fID; // id of edge generating data 312cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com uint8_t fVerb; // FIXME: not read from everywhere 3132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fCloseCall; // edge is trimmable if not originally coincident 314f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com}; 315f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 3166680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comclass OutEdgeBuilder { 3176680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.compublic: 318f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com OutEdgeBuilder(bool fill) 319f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com : fFill(fill) { 320f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 321f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 322a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com void addCurve(const SkPoint line[4], SkPath::Verb verb, int id, 323a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bool closeCall) { 324c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com OutEdge& newEdge = fEdges.push_back(); 325a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com memcpy(newEdge.fPts, line, (verb + 1) * sizeof(SkPoint)); 326a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com newEdge.fVerb = verb; 3272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com newEdge.fID = id; 3282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com newEdge.fCloseCall = closeCall; 3292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 330752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 3312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool trimLine(SkScalar y, int id) { 3322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t count = fEdges.count(); 3332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (count-- != 0) { 3342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com OutEdge& edge = fEdges[count]; 3352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fID != id) { 3362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 3372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fCloseCall) { 3392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 3402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(edge.fPts[0].fY <= y); 3422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fPts[1].fY <= y) { 3432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 3442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge.fPts[1].fX = edge.fPts[0].fX + (y - edge.fPts[0].fY) 3462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com * (edge.fPts[1].fX - edge.fPts[0].fX) 3472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com / (edge.fPts[1].fY - edge.fPts[0].fY); 3482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge.fPts[1].fY = y; 3492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (gShowDebugf) { 3502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s edge=%d %1.9g,%1.9g\n", __FUNCTION__, id, 3512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge.fPts[1].fX, y); 3522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return true; 3542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 356f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 357f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 358f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com void assemble(SkPath& simple) { 3596008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t listCount = fEdges.count(); 3606008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (listCount == 0) { 3616008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return; 3626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 363f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 3646008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t listIndex = 0; 3656008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int advance = 1; 3666008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (listIndex < listCount && fTops[listIndex] == 0) { 3676008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++listIndex; 368f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 3696008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (listIndex >= listCount) { 3706008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com break; 371f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 3724917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com int closeEdgeIndex = -listIndex - 1; 373fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // the curve is deferred and not added right away because the 374fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // following edge may extend the first curve. 375a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint firstPt, lastCurve[4]; 376a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com uint8_t lastVerb; 377fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 378fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int firstIndex, lastIndex; 379fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com const int tab = 8; 380fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 3816008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool doMove = true; 3826008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int edgeIndex; 3836008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com do { 384cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkPoint* ptArray = fEdges[listIndex].fPts; 385cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com uint8_t verb = fEdges[listIndex].fVerb; 386fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint* curve[4]; 3876008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance < 0) { 388fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0] = &ptArray[verb]; 389fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kCubic_Verb) { 390fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[2]; 391fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[2] = &ptArray[1]; 392fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 393fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[verb] = &ptArray[0]; 3946008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 395fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0] = &ptArray[0]; 396fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kCubic_Verb) { 397fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[1]; 398fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[2] = &ptArray[2]; 399fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 400fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[verb] = &ptArray[verb]; 401fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 402fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kQuad_Verb) { 403fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[1]; 404f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 405a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (doMove) { 406fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstPt = *curve[0]; 407fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.moveTo(curve[0]->fX, curve[0]->fY); 408fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 409fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s %d moveTo (%g,%g)\n", __FUNCTION__, 410fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com listIndex + 1, curve[0]->fX, curve[0]->fY); 411fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstIndex = listIndex; 412fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 413fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 0; index <= verb; ++index) { 414fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[index] = *curve[index]; 415a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 416a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com doMove = false; 417a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 418fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bool gap = lastCurve[lastVerb] != *curve[0]; 419fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (gap || lastVerb != SkPath::kLine_Verb) { // output the accumulated curve before the gap 420a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: see comment in bridge -- this probably 421a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // conceals errors 422fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fFill && UlpsDiff(lastCurve[lastVerb].fY, 423fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0]->fY) <= 10); 424a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (lastVerb) { 425a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 426a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.lineTo(lastCurve[1].fX, lastCurve[1].fY); 427a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 428a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 429a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.quadTo(lastCurve[1].fX, lastCurve[1].fY, 430a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[2].fX, lastCurve[2].fY); 431a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 432a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 433a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY, 434a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[2].fX, lastCurve[2].fY, 435a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[3].fX, lastCurve[3].fY); 436a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 437cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 438fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 439fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d %sTo (%g,%g)\n", tab, "", lastIndex + 1, 440fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kLVerbStr[lastVerb], lastCurve[lastVerb].fX, 441fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[lastVerb].fY); 442fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 443a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 444fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int firstCopy = 1; 445fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (gap || (lastVerb == SkPath::kLine_Verb && 446fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com !extendLine(lastCurve, *curve[verb]))) { 447a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: see comment in bridge -- this probably 448a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // conceals errors 449fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(lastCurve[lastVerb] == *curve[0] || 450fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com (fFill && UlpsDiff(lastCurve[lastVerb].fY, 451fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0]->fY) <= 10)); 452fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(curve[0]->fX, curve[0]->fY); 453fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 454fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d gap lineTo (%g,%g)\n", tab, "", 455fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex + 1, curve[0]->fX, curve[0]->fY); 456fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 457fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstCopy = 0; 458fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else if (lastVerb != SkPath::kLine_Verb) { 459fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstCopy = 0; 460a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 461fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = firstCopy; index <= verb; ++index) { 462fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[index] = *curve[index]; 463a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 4646008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 465fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastVerb = verb; 466fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 467fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex = listIndex; 468fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 4696008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance < 0) { 4706008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com edgeIndex = fTops[listIndex]; 4716008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[listIndex] = 0; 472fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 4736008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com edgeIndex = fBottoms[listIndex]; 4746008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[listIndex] = 0; 4756008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 4764917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex) { 4774917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com listIndex = abs(edgeIndex) - 1; 4784917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex < 0) { 4794917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fTops[listIndex] = 0; 4804917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } else { 4814917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fBottoms[listIndex] = 0; 4824917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 4834917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 4844917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex == closeEdgeIndex || edgeIndex == 0) { 485fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com switch (lastVerb) { 486fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kLine_Verb: 487fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(lastCurve[1].fX, lastCurve[1].fY); 488fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 489fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kQuad_Verb: 490fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.quadTo(lastCurve[1].fX, lastCurve[1].fY, 491fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[2].fX, lastCurve[2].fY); 492fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 493fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kCubic_Verb: 494fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY, 495fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[2].fX, lastCurve[2].fY, 496fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[3].fX, lastCurve[3].fY); 497fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 498fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 499fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 500fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d %sTo last (%g, %g)\n", tab, "", 501fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex + 1, kLVerbStr[lastVerb], 502fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[lastVerb].fX, lastCurve[lastVerb].fY); 503fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 504a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (lastCurve[lastVerb] != firstPt) { 505fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(firstPt.fX, firstPt.fY); 506fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 507fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d final line (%g, %g)\n", tab, "", 508fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstIndex + 1, firstPt.fX, firstPt.fY); 509fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 5104917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 511cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com simple.close(); 512fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 513fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s close\n", tab, ""); 514fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 515cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com break; 516cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 517fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // if this and next edge go different directions 518fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 519fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s advance=%d edgeIndex=%d flip=%s\n", tab, "", 520fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com advance, edgeIndex, advance > 0 ^ edgeIndex < 0 ? 521fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com "true" : "false"); 522fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 5236008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance > 0 ^ edgeIndex < 0) { 5246008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com advance = -advance; 5256008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 5264917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } while (edgeIndex); 5276008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } while (true); 528f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 529752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 530cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // sort points by y, then x 531cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if x/y is identical, sort bottoms before tops 532cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if identical and both tops/bottoms, sort by angle 533cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com static bool lessThan(SkTArray<OutEdge>& edges, const int one, 534cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const int two) { 535cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const OutEdge& oneEdge = edges[abs(one) - 1]; 536cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com int oneIndex = one < 0 ? 0 : oneEdge.fVerb; 537cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& startPt1 = oneEdge.fPts[oneIndex]; 538cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const OutEdge& twoEdge = edges[abs(two) - 1]; 539cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com int twoIndex = two < 0 ? 0 : twoEdge.fVerb; 540cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& startPt2 = twoEdge.fPts[twoIndex]; 541cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (startPt1.fY != startPt2.fY) { 5422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d (%g,%g) %s startPt1.fY < startPt2.fY\n", __FUNCTION__, 5442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, startPt1.fY, startPt2.fY, 5452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com startPt1.fY < startPt2.fY ? "true" : "false"); 5462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 547cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return startPt1.fY < startPt2.fY; 548cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 549cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (startPt1.fX != startPt2.fX) { 5502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d (%g,%g) %s startPt1.fX < startPt2.fX\n", __FUNCTION__, 5522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, startPt1.fX, startPt2.fX, 5532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com startPt1.fX < startPt2.fX ? "true" : "false"); 5542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 555cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return startPt1.fX < startPt2.fX; 556cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 557cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& endPt1 = oneEdge.fPts[oneIndex ^ oneEdge.fVerb]; 558cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& endPt2 = twoEdge.fPts[twoIndex ^ twoEdge.fVerb]; 559cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy1 = startPt1.fY - endPt1.fY; 560cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy2 = startPt2.fY - endPt2.fY; 561cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy1y2 = dy1 * dy2; 562cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (dy1y2 < 0) { // different signs 5632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 564cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkDebugf("%s %d<%d %s dy1 > 0\n", __FUNCTION__, one, two, 565cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com dy1 > 0 ? "true" : "false"); 5662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 567cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return dy1 > 0; // one < two if one goes up and two goes down 568cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 569cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (dy1y2 == 0) { 5702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d %s endPt1.fX < endPt2.fX\n", __FUNCTION__, 5722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, endPt1.fX < endPt2.fX ? "true" : "false"); 5732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 574cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return endPt1.fX < endPt2.fX; 575cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 576cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dx1y2 = (startPt1.fX - endPt1.fX) * dy2; 577cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dx2y1 = (startPt2.fX - endPt2.fX) * dy1; 5782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d %s dy2 < 0 ^ dx1y2 < dx2y1\n", __FUNCTION__, 5802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, dy2 < 0 ^ dx1y2 < dx2y1 ? "true" : "false"); 5812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 582cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return dy2 > 0 ^ dx1y2 < dx2y1; 583f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 584f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 5856008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // Sort the indices of paired points and then create more indices so 5866008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // assemble() can find the next edge and connect the top or bottom 587f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com void bridge() { 588f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t index; 589f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t count = fEdges.count(); 590f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com if (!count) { 591f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return; 592f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 593cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkASSERT(!fFill || count > 1); 594f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com fTops.setCount(count); 595f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com sk_bzero(fTops.begin(), sizeof(fTops[0]) * count); 596f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com fBottoms.setCount(count); 597f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com sk_bzero(fBottoms.begin(), sizeof(fBottoms[0]) * count); 5986008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> order; 5996008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 1; index <= count; ++index) { 6006008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com *order.append() = -index; 601f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 602cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com for (index = 1; index <= count; ++index) { 603cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com *order.append() = index; 604cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 605cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com QSort<SkTArray<OutEdge>, int>(fEdges, order.begin(), order.end() - 1, lessThan); 6066008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int* lastPtr = order.end() - 1; 6076008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int* leftPtr = order.begin(); 6086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (leftPtr < lastPtr) { 6096008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int leftIndex = *leftPtr; 6106008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int leftOutIndex = abs(leftIndex) - 1; 6116008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const OutEdge& left = fEdges[leftOutIndex]; 612f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int* rightPtr = leftPtr + 1; 6136008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int rightIndex = *rightPtr; 6146008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int rightOutIndex = abs(rightIndex) - 1; 6156008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const OutEdge& right = fEdges[rightOutIndex]; 616cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool pairUp = fFill; 617cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (!pairUp) { 618cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& leftMatch = 619cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com left.fPts[leftIndex < 0 ? 0 : left.fVerb]; 620cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& rightMatch = 621cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb]; 622cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com pairUp = leftMatch == rightMatch; 623cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } else { 6242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT 625d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // FIXME : not happy that error in low bit is allowed 626d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // this probably conceals error elsewhere 627d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY, 628d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) > 1) { 6292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *fMismatches.append() = leftIndex; 6302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (rightPtr == lastPtr) { 6312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *fMismatches.append() = rightIndex; 6322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 6332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com pairUp = false; 6342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 6352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #else 636d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkASSERT(UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY, 637d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) <= 10); 6382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 639cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 640cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (pairUp) { 6416008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (leftIndex < 0) { 6426008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[leftOutIndex] = rightIndex; 6436008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 6446008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[leftOutIndex] = rightIndex; 6456008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 6466008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (rightIndex < 0) { 6476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[rightOutIndex] = leftIndex; 6486008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 6496008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[rightOutIndex] = leftIndex; 650f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 6516008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++rightPtr; 652f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 653f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com leftPtr = rightPtr; 6546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 6552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_OUT 6562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int* mismatch = fMismatches.begin(); 6572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (mismatch != fMismatches.end()) { 6582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int leftIndex = *mismatch++; 6592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int leftOutIndex = abs(leftIndex) - 1; 6602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const OutEdge& left = fEdges[leftOutIndex]; 6612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const SkPoint& leftPt = left.fPts[leftIndex < 0 ? 0 : left.fVerb]; 6622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s left=%d %s (%1.9g,%1.9g)\n", 6632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com __FUNCTION__, left.fID, leftIndex < 0 ? "top" : "bot", 6642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com leftPt.fX, leftPt.fY); 6652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 6662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(fMismatches.count() == 0); 6672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 668fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_BRIDGE 669fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < count; ++index) { 670fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com const OutEdge& edge = fEdges[index]; 671fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com uint8_t verb = edge.fVerb; 672fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s %d edge=%d %s (%1.9g,%1.9g) (%1.9g,%1.9g)\n", 673fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com index == 0 ? __FUNCTION__ : " ", 674fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com index + 1, edge.fID, kLVerbStr[verb], edge.fPts[0].fX, 675fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge.fPts[0].fY, edge.fPts[verb].fX, edge.fPts[verb].fY); 676fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 677fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < count; ++index) { 678fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf(" top of % 2d connects to %s of % 2d\n", index + 1, 679fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fTops[index] < 0 ? "top " : "bottom", abs(fTops[index])); 680fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf(" bottom of % 2d connects to %s of % 2d\n", index + 1, 681fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fBottoms[index] < 0 ? "top " : "bottom", abs(fBottoms[index])); 682fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 683fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 6846680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 6856680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 6866008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.comprotected: 6876680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTArray<OutEdge> fEdges; 6886008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> fTops; 6896008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> fBottoms; 690f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com bool fFill; 6912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_OUT 6922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<int> fMismatches; 6932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 6946680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com}; 6956680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 696c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com// Bounds, unlike Rect, does not consider a vertical line to be empty. 697c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comstruct Bounds : public SkRect { 698c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com static bool Intersects(const Bounds& a, const Bounds& b) { 699c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return a.fLeft <= b.fRight && b.fLeft <= a.fRight && 700c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com a.fTop <= b.fBottom && b.fTop <= a.fBottom; 701c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 702752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 7036008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool isEmpty() { 7046008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return fLeft > fRight || fTop > fBottom 7056008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com || fLeft == fRight && fTop == fBottom 7066008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com || isnan(fLeft) || isnan(fRight) 7076008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com || isnan(fTop) || isnan(fBottom); 7086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 709c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 710c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 7114917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.comclass Intercepts { 7124917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.compublic: 7134917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com Intercepts() 7144917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com : fTopIntercepts(0) 715198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fBottomIntercepts(0) 716198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fExplicit(false) { 717198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 718198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 719198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com Intercepts& operator=(const Intercepts& src) { 720198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTs = src.fTs; 721198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTopIntercepts = src.fTopIntercepts; 722198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fBottomIntercepts = src.fBottomIntercepts; 723198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 724198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 725198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: remove this function if it's never called 726198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double t(int tIndex) const { 727198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (tIndex == 0) { 728198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return 0; 729198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 730198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (tIndex > fTs.count()) { 731198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return 1; 732198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 733198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return fTs[tIndex - 1]; 7344917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 735752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 7362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 737a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com void dump(const SkPoint* pts, SkPath::Verb verb) { 7382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "Intercepts"; 7392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 8; 7402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (int i = 0; i < fTs.count(); ++i) { 7412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkPoint out; 742a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (verb) { 743a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 744a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(pts, fTs[i], &out); 745a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 746a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 747a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com QuadXYAtT(pts, fTs[i], &out); 748a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 749a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 750a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com CubicXYAtT(pts, fTs[i], &out); 751a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 752a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 753a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 754a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 755752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fTs[%d]=%1.9g (%1.9g,%1.9g)\n", tab + sizeof(className), 7562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fTs[i], out.fX, out.fY); 7572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 758198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fTopIntercepts=%u\n", tab + sizeof(className), 7592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fTopIntercepts); 760198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fBottomIntercepts=%u\n", tab + sizeof(className), 7612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fBottomIntercepts); 762fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s.fExplicit=%d\n", tab + sizeof(className), 763fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com className, fExplicit); 7642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 7652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 7662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 767c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<double> fTs; 768198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com unsigned char fTopIntercepts; // 0=init state 1=1 edge >1=multiple edges 769198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com unsigned char fBottomIntercepts; 770198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fExplicit; // if set, suppress 0 and 1 771198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 772c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 773c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 7742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstruct HorizontalEdge { 7752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool operator<(const HorizontalEdge& rh) const { 7762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fY == rh.fY ? fLeft == rh.fLeft ? fRight < rh.fRight 7772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com : fLeft < rh.fLeft : fY < rh.fY; 7782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 7792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 7802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 7812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void dump() { 7822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "HorizontalEdge"; 7832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 4; 784752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fLeft=%1.9g\n", tab + sizeof(className), className, fLeft); 785752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fRight=%1.9g\n", tab + sizeof(className), className, fRight); 786752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fY=%1.9g\n", tab + sizeof(className), className, fY); 7872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 7882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 7892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 7902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fLeft; 7912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fRight; 7922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fY; 7932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com}; 7942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 7956680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstruct InEdge { 7966680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool operator<(const InEdge& rh) const { 797c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return fBounds.fTop == rh.fBounds.fTop 798c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ? fBounds.fLeft < rh.fBounds.fLeft 799c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com : fBounds.fTop < rh.fBounds.fTop; 800c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 801c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 8022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // Avoid collapsing t values that are close to the same since 8032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // we walk ts to describe consecutive intersections. Since a pair of ts can 8042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // be nearly equal, any problems caused by this should be taken care 8052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // of later. 8062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int add(double* ts, size_t count, ptrdiff_t verbIndex) { 807c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: in the pathological case where there is a ton of intercepts, binary search? 8086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool foundIntercept = false; 8092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int insertedAt = -1; 8106008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com Intercepts& intercepts = fIntercepts[verbIndex]; 811c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < count; ++index) { 812c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com double t = ts[index]; 8134917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (t <= 0) { 814198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intercepts.fTopIntercepts <<= 1; 8154917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= ++intercepts.fTopIntercepts > 1; 8164917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com continue; 8174917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 8184917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (t >= 1) { 819198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intercepts.fBottomIntercepts <<= 1; 8204917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= ++intercepts.fBottomIntercepts > 1; 8216008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com continue; 8226008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 823198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntersected = true; 8246008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com foundIntercept = true; 825c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t tCount = intercepts.fTs.count(); 8262e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double delta; 827c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t idx2 = 0; idx2 < tCount; ++idx2) { 828c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (t <= intercepts.fTs[idx2]) { 8292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: ? if (t < intercepts.fTs[idx2]) // failed 8302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com delta = intercepts.fTs[idx2] - t; 831cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (delta > 0) { 8322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com insertedAt = idx2; 833c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *intercepts.fTs.insert(idx2) = t; 834c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com goto nextPt; 836c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 837c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (tCount == 0 || (delta = t - intercepts.fTs[tCount - 1]) > 0) { 8392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com insertedAt = tCount; 840c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *intercepts.fTs.append() = t; 841c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPt: 8432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ; 844c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8454917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= foundIntercept; 8462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return insertedAt; 847c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 848198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 849fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void addPartial(SkTArray<InEdge>& edges, int ptStart, int ptEnd, 850198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int verbStart, int verbEnd) { 851198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge* edge = edges.push_back_n(1); 852198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int verbCount = verbEnd - verbStart; 853198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts.push_back_n(verbCount); 854198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t* verbs = &fVerbs[verbStart]; 855198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int ceptIdx = 0; ceptIdx < verbCount; ++ceptIdx) { 856198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts[ceptIdx] = fIntercepts[verbStart + ceptIdx]; 857198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 858198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fPts.append(ptEnd - ptStart, &fPts[ptStart]); 859198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fVerbs.append(verbCount, &fVerbs[verbStart]); 860198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->setBounds(); 861198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fWinding = fWinding; 862198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know? 863198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 864198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 865fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void addSplit(SkTArray<InEdge>& edges, SkPoint* pts, uint8_t verb, 866fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts, int firstT, int lastT, bool flipped) { 867198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge* edge = edges.push_back_n(1); 868198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts.push_back_n(1); 869fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (firstT == 0) { 870fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = 0; 871fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 872fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = intercepts.fTs[firstT - 1]; 873fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 874fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bool add1 = lastT == intercepts.fTs.count(); 875fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fIntercepts[0].fTs.append(lastT - firstT, &intercepts.fTs[firstT]); 876fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (add1) { 877fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = 1; 878fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 879198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts[0].fExplicit = true; 880fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fPts.append(verb + 1, pts); 881198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fVerbs.append(1, &verb); 882fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // FIXME: bounds could be better for partial Ts 883fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->setSubBounds(); 884198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know? 885198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (flipped) { 886fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->flipTs(); 887fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fWinding = -fWinding; 888fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 889fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fWinding = fWinding; 890198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 891198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 892c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 8936680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool cached(const InEdge* edge) { 894c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: in the pathological case where there is a ton of edges, binary search? 895c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t count = fCached.count(); 896c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < count; ++index) { 897c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edge == fCached[index]) { 898c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return true; 899c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 900c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edge < fCached[index]) { 901c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCached.insert(index) = edge; 902c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 903c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 904c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 905c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCached.append() = edge; 906c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 907c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 908c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 909fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void complete(signed char winding) { 910198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com setBounds(); 911198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntercepts.push_back_n(fVerbs.count()); 912198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if ((fWinding = winding) < 0) { // reverse verbs, pts, if bottom to top 913198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com flip(); 914198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 915198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsIntercepts = fIntersected = false; 916198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 917198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 918fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void flip() { 919198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t index; 920198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t last = fPts.count() - 1; 921198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (index = 0; index < last; ++index, --last) { 922198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTSwap<SkPoint>(fPts[index], fPts[last]); 923198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 924198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com last = fVerbs.count() - 1; 925198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (index = 0; index < last; ++index, --last) { 926198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTSwap<uint8_t>(fVerbs[index], fVerbs[last]); 927198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 928198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 929fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 930fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void flipTs() { 931fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fIntercepts.count() == 1); 932fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts = fIntercepts[0]; 933fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(intercepts.fExplicit); 934fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTDArray<double>& ts = intercepts.fTs; 935fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com size_t index; 936fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com size_t last = ts.count() - 1; 937fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < last; ++index, --last) { 938fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTSwap<double>(ts[index], ts[last]); 939fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 940fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 941198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 942198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com void reset() { 943198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fCached.reset(); 944198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntercepts.reset(); 945198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fPts.reset(); 946198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fVerbs.reset(); 947198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); 948198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fWinding = 0; 949198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsIntercepts = false; 950198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntersected = false; 951198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 952198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 953198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com void setBounds() { 954c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint* ptPtr = fPts.begin(); 955c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint* ptLast = fPts.end(); 956c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (ptPtr == ptLast) { 957198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s empty edge\n", __FUNCTION__); 958c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkASSERT(0); 959c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: delete empty edge? 960c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 961c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 962c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fBounds.set(ptPtr->fX, ptPtr->fY, ptPtr->fX, ptPtr->fY); 963c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ++ptPtr; 964c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while (ptPtr != ptLast) { 965c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fBounds.growToInclude(ptPtr->fX, ptPtr->fY); 966c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ++ptPtr; 967c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 968198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 969fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 970fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // recompute bounds based on subrange of T values 971fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void setSubBounds() { 972fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fIntercepts.count() == 1); 973fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts = fIntercepts[0]; 974fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(intercepts.fExplicit); 975fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fVerbs.count() == 1); 976fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTDArray<double>& ts = intercepts.fTs; 977fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (fVerbs[0] == SkPath::kQuad_Verb) { 978fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fPts.count() == 3); 979fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com QuadSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds); 980fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 981fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fVerbs[0] == SkPath::kCubic_Verb); 982fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fPts.count() == 4); 983fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com CubicSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds); 984fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 985fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 986198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 987fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void splitInflectionPts(SkTArray<InEdge>& edges) { 988198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (!fIntersected) { 989198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return; 990198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 991198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t* verbs = fVerbs.begin(); 992198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkPoint* pts = fPts.begin(); 993198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastVerb = 0; 994198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastPt = 0; 995198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t verb; 996198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool edgeSplit = false; 997198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int ceptIdx = 0; ceptIdx < fIntercepts.count(); ++ceptIdx, pts += verb) { 998198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com Intercepts& intercepts = fIntercepts[ceptIdx]; 999198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com verb = *verbs++; 1000198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (verb <= SkPath::kLine_Verb) { 1001198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com continue; 1002198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1003198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t tCount = intercepts.fTs.count(); 1004198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (!tCount) { 1005198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com continue; 1006198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1007198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t tIndex = -1; 1008198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y = pts[0].fY; 1009198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastSplit = 0; 1010198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int firstSplit = -1; 1011198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool curveSplit = false; 1012198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com while (++tIndex < tCount) { 1013198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double nextT = intercepts.fTs[tIndex]; 1014198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar nextY = verb == SkPath::kQuad_Verb 1015198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com ? QuadYAtT(pts, nextT) : CubicYAtT(pts, nextT); 1016198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (nextY < y) { 1017198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edgeSplit = curveSplit = true; 1018198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit < 0) { 1019198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = tIndex; 1020198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextPt = pts - fPts.begin(); 1021198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextVerb = verbs - 1 - fVerbs.begin(); 1022198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastVerb < nextVerb) { 1023fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addPartial(edges, lastPt, nextPt, lastVerb, nextVerb); 1024198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1025fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addPartial 1\n", __FUNCTION__); 1026198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1027198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1028198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastPt = nextPt; 1029198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastVerb = nextVerb; 1030198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1031198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } else { 1032198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit >= 0) { 1033198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastSplit < firstSplit) { 1034fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, 1035fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastSplit, firstSplit, false); 1036198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1037fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 1 tIndex=%d,%d\n", 1038fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com __FUNCTION__, lastSplit, firstSplit); 1039198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1040198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1041fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, 1042fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, tIndex, true); 1043198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1044fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 2 tIndex=%d,%d flip\n", 1045fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com __FUNCTION__, firstSplit, tIndex); 1046198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1047198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastSplit = tIndex; 1048198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = -1; 1049198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1050198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1051198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com y = nextY; 1052198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1053198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (curveSplit) { 1054198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit < 0) { 1055198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = lastSplit; 1056198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } else { 1057fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, lastSplit, 1058fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, false); 1059198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1060fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 3 tIndex=%d,%d\n", __FUNCTION__, 1061fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastSplit, firstSplit); 1062198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1063198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1064fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, firstSplit, 1065fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com tIndex, pts[verb].fY < y); 1066198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1067fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 4 tIndex=%d,%d %s\n", __FUNCTION__, 1068fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, tIndex, pts[verb].fY < y ? "flip" : ""); 1069198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 10706680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1071198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1072198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // collapse remainder -- if there's nothing left, clear it somehow? 1073198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (edgeSplit) { 1074198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextVerb = verbs - 1 - fVerbs.begin(); 1075198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastVerb < nextVerb) { 1076198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextPt = pts - fPts.begin(); 1077fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addPartial(edges, lastPt, nextPt, lastVerb, nextVerb); 1078198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1079fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addPartial 2\n", __FUNCTION__); 1080198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 10816680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1082198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: reuse the edge instead of marking it empty 1083198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com reset(); 10846680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 10852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 10862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 10872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 10882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void dump() { 10892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int i; 10902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "InEdge"; 10912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 4; 10922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("InEdge %p (edge=%d)\n", this, fID); 10932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fCached.count(); ++i) { 10942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fCached[%d]=0x%08x\n", tab + sizeof(className), 10952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fCached[i]); 10962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 10972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com uint8_t* verbs = fVerbs.begin(); 10982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkPoint* pts = fPts.begin(); 10992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fIntercepts.count(); ++i) { 11002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fIntercepts[%d]:\n", tab + sizeof(className), 11012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i); 1102a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fIntercepts[i].dump(pts, (SkPath::Verb) *verbs); 11032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com pts += *verbs++; 11042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fPts.count(); ++i) { 1106752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fPts[%d]=(%1.9g,%1.9g)\n", tab + sizeof(className), 11072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fPts[i].fX, fPts[i].fY); 11082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fVerbs.count(); ++i) { 11102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fVerbs[%d]=%d\n", tab + sizeof(className), 11112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fVerbs[i]); 11122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1113fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s.fBounds=(%1.9g, %1.9g, %1.9g, %1.9g)\n", tab + sizeof(className), 11142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fBounds.fLeft, fBounds.fTop, 11152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fBounds.fRight, fBounds.fBottom); 11162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fWinding=%d\n", tab + sizeof(className), className, 11172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fWinding); 11182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className), 11192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fContainsIntercepts); 1120198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fIntersected=%d\n", tab + sizeof(className), 1121198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com className, fIntersected); 1122c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 11232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 1124c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1125198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: temporary data : move this to a separate struct? 11266680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTDArray<const InEdge*> fCached; // list of edges already intercepted 1127c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTArray<Intercepts> fIntercepts; // one per verb 11284917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com 1129c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // persistent data 1130c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<SkPoint> fPts; 1131c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<uint8_t> fVerbs; 1132c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com Bounds fBounds; 11332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fID; 1134c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com signed char fWinding; 11356680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool fContainsIntercepts; 1136198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fIntersected; 1137c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1138c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 11396680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comclass InEdgeBuilder { 1140c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.compublic: 1141c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 11422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comInEdgeBuilder(const SkPath& path, bool ignoreHorizontal, SkTArray<InEdge>& edges, 11432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge>& horizontalEdges) 1144c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com : fPath(path) 1145c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fCurrentEdge(NULL) 1146c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fEdges(edges) 11472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com , fHorizontalEdges(horizontalEdges) 1148c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fIgnoreHorizontal(ignoreHorizontal) 1149198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fContainsCurves(false) 1150c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com{ 1151c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com walk(); 1152c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1153c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1154198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.combool containsCurves() const { 1155198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return fContainsCurves; 1156198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 1157198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 1158c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comprotected: 1159c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1160c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid addEdge() { 1161f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 1162c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fCurrentEdge->fPts.append(fPtCount - fPtOffset, &fPts[fPtOffset]); 1163c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fPtOffset = 1; 1164c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCurrentEdge->fVerbs.append() = fVerb; 1165c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1166c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 11676008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.combool complete() { 11686008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (fCurrentEdge && fCurrentEdge->fVerbs.count()) { 1169fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fCurrentEdge->complete(fWinding); 11706008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fCurrentEdge = NULL; 11716008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return true; 11726008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 11736008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return false; 11746008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com} 11756008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 1176c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comint direction(int count) { 1177c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fPtCount = count; 11782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fIgnoreHorizontal && isHorizontal()) { 1179c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return 0; 1180c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1181c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int last = count - 1; 1182c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return fPts[0].fY == fPts[last].fY 11836680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com ? fPts[0].fX == fPts[last].fX ? 0 : fPts[0].fX < fPts[last].fX 11846680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com ? 1 : -1 : fPts[0].fY < fPts[last].fY ? 1 : -1; 1185c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1186c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1187c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.combool isHorizontal() { 1188c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkScalar y = fPts[0].fY; 1189c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (int i = 1; i < fPtCount; ++i) { 1190c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (fPts[i].fY != y) { 1191c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 1192c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1193c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1194c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return true; 1195c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1196c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1197c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid startEdge() { 11986008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (!fCurrentEdge) { 11996008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fCurrentEdge = fEdges.push_back_n(1); 12006008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 1201c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fWinding = 0; 1202c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fPtOffset = 0; 1203c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1204c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1205c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid walk() { 1206c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Iter iter(fPath, true); 12072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int winding = 0; 1208c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while ((fVerb = iter.next(fPts)) != SkPath::kDone_Verb) { 1209c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com switch (fVerb) { 1210c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kMove_Verb: 1211c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com startEdge(); 1212c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1213c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kLine_Verb: 1214c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com winding = direction(2); 1215c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1216c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kQuad_Verb: 1217c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com winding = direction(3); 1218198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsCurves = true; 1219c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1220c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kCubic_Verb: 1221c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com winding = direction(4); 1222198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsCurves = true; 1223c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1224c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kClose_Verb: 1225f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 12266008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com complete(); 1227c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1228c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com default: 1229c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkDEBUGFAIL("bad verb"); 1230c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 1231c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 12322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (winding == 0) { 12332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge* horizontalEdge = fHorizontalEdges.append(); 12342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: for degenerate quads and cubics, compute x extremes 12352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fLeft = fPts[0].fX; 12362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fRight = fPts[fVerb].fX; 12372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fY = fPts[0].fY; 12382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (horizontalEdge->fLeft > horizontalEdge->fRight) { 12392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTSwap<SkScalar>(horizontalEdge->fLeft, horizontalEdge->fRight); 12402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 12416008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (complete()) { 12426008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com startEdge(); 12436008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 1244c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1245c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1246c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (fWinding + winding == 0) { 1247c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: if prior verb or this verb is a horizontal line, reverse 1248c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // it instead of starting a new edge 1249f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 1250cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (complete()) { 1251cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com startEdge(); 1252cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1253c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1254c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fWinding = winding; 1255c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com addEdge(); 1256c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 12576b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (!complete()) { 12586b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (fCurrentEdge) { 12596b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com fEdges.pop_back(); 12606b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 12616b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 1262c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1263c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1264c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comprivate: 1265c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const SkPath& fPath; 12666680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com InEdge* fCurrentEdge; 12676680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTArray<InEdge>& fEdges; 12682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge>& fHorizontalEdges; 1269c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint fPts[4]; 1270c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb fVerb; 1271c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int fPtCount; 1272c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int fPtOffset; 1273c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int8_t fWinding; 1274c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bool fIgnoreHorizontal; 1275198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fContainsCurves; 1276c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1277c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 12786680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstruct WorkEdge { 1279c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkScalar bottom() const { 12806680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fPts[verb()].fY; 1281c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1282c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 12836680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void init(const InEdge* edge) { 12846680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fEdge = edge; 12856680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fPts = edge->fPts.begin(); 12866680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fVerb = edge->fVerbs.begin(); 1287c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1288c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1289cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool advance() { 12906680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkASSERT(fVerb < fEdge->fVerbs.end()); 12916680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fPts += *fVerb++; 12926680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fVerb != fEdge->fVerbs.end(); 1293c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1294752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1295cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPath::Verb lastVerb() const { 1296cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkASSERT(fVerb > fEdge->fVerbs.begin()); 1297cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return (SkPath::Verb) fVerb[-1]; 1298cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1299cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com 1300c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1301c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb verb() const { 1302c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return (SkPath::Verb) *fVerb; 1303c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1304c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13056008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ptrdiff_t verbIndex() const { 13066680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fVerb - fEdge->fVerbs.begin(); 13076680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1308752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 13096680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com int winding() const { 13106680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fEdge->fWinding; 1311c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1312c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13136680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com const InEdge* fEdge; 1314c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const SkPoint* fPts; 1315c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const uint8_t* fVerb; 1316c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1317c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13186680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// always constructed with SkTDArray because new edges are inserted 13196680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// this may be a inappropriate optimization, suggesting that a separate array of 13206680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// ActiveEdge* may be faster to insert and search 1321cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com 1322cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com// OPTIMIZATION: Brian suggests that global sorting should be unnecessary, since 1323cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com// as active edges are introduced, only local sorting should be required 13242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comclass ActiveEdge { 13252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.compublic: 13266008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool operator<(const ActiveEdge& rh) const { 1327d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com double topD = fAbove.fX - rh.fAbove.fX; 1328d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (rh.fAbove.fY < fAbove.fY) { 1329d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com topD = (rh.fBelow.fY - rh.fAbove.fY) * topD 1330d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com - (fAbove.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX); 1331d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else if (rh.fAbove.fY > fAbove.fY) { 1332d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com topD = (fBelow.fY - fAbove.fY) * topD 1333d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com + (rh.fAbove.fY - fAbove.fY) * (fBelow.fX - fAbove.fX); 1334d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1335d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com double botD = fBelow.fX - rh.fBelow.fX; 1336d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (rh.fBelow.fY > fBelow.fY) { 1337d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com botD = (rh.fBelow.fY - rh.fAbove.fY) * botD 1338d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com - (fBelow.fY - rh.fBelow.fY) * (rh.fBelow.fX - rh.fAbove.fX); 1339d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else if (rh.fBelow.fY < fBelow.fY) { 1340d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com botD = (fBelow.fY - fAbove.fY) * botD 1341d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com + (rh.fBelow.fY - fBelow.fY) * (fBelow.fX - fAbove.fX); 1342d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1343d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // return sign of greater absolute value 1344d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com return (fabs(topD) > fabs(botD) ? topD : botD) < 0; 1345d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1346d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com 1347d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // OPTIMIZATION: fold return statements into one 1348d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com bool operator_less_than(const ActiveEdge& rh) const { 1349cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (rh.fAbove.fY - fAbove.fY > fBelow.fY - rh.fAbove.fY 1350cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && fBelow.fY < rh.fBelow.fY 1351cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com || fAbove.fY - rh.fAbove.fY < rh.fBelow.fY - fAbove.fY 1352cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && rh.fBelow.fY < fBelow.fY) { 1353cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // FIXME: need to compute distance, not check for points equal 1354cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com const SkPoint& check = rh.fBelow.fY <= fBelow.fY 1355cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && fBelow != rh.fBelow ? rh.fBelow : 1356cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com rh.fAbove; 13572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_ACTIVE_LESS_THAN 13582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s 1 %c %cthis (edge=%d) {%g,%g %g,%g}" 13592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com " < rh (edge=%d) {%g,%g %g,%g} upls=(%d)\n", __FUNCTION__, 13602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com rh.fBelow.fY <= fBelow.fY && fBelow != rh.fBelow ? 'B' : 'A', 13612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX) 13622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com < (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX) ? ' ' 13632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com : '!', ID(), fAbove.fX, fAbove.fY, fBelow.fX, fBelow.fY, 13642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com rh.ID(), rh.fAbove.fX, rh.fAbove.fY, rh.fBelow.fX, rh.fBelow.fY, 13652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com UlpsDiff((check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX), 13662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX))); 13672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 1368cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return (check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX) 1369cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com < (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX); 1370cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1371cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // FIXME: need to compute distance, not check for points equal 1372cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com const SkPoint& check = fBelow.fY <= rh.fBelow.fY 1373cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && fBelow != rh.fBelow ? fBelow : fAbove; 13742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_ACTIVE_LESS_THAN 13752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s 2 %c %cthis (edge=%d) {%g,%g %g,%g}" 1376752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com " < rh (edge=%d) {%g,%g %g,%g} upls=(%d) (%d,%d)\n", __FUNCTION__, 1377752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com fBelow.fY <= rh.fBelow.fY && fBelow != rh.fBelow ? 'B' : 'A', 13782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX) 13792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com < (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX) 13802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ? ' ' : '!', ID(), fAbove.fX, fAbove.fY, fBelow.fX, fBelow.fY, 13812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com rh.ID(), rh.fAbove.fX, rh.fAbove.fY, rh.fBelow.fX, rh.fBelow.fY, 13822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com UlpsDiff((rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX), 1383752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX)), 1384752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com UlpsDiff(fBelow.fX, rh.fBelow.fX), UlpsDiff(fBelow.fY, rh.fBelow.fY)); 13852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 1386cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return (rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX) 1387cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com < (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX); 13886008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 1389752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 13902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // If a pair of edges are nearly coincident for some span, add a T in the 13912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // edge so it can be shortened to match the other edge. Note that another 13922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // approach is to trim the edge after it is added to the OutBuilder list -- 13932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: since this has no effect if the edge is already done (i.e., 13942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fYBottom >= y) maybe this can only be done by calling trimLine later. 13952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYBelow(SkScalar y) { 13962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fBelow.fY <= y || fYBottom >= y) { 13972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 13982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 13992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addTatYInner(y); 14002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fFixBelow = true; 14012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1402752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 14032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYAbove(SkScalar y) { 14042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fBelow.fY <= y) { 14052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 14062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addTatYInner(y); 14082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 14102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYInner(SkScalar y) { 1411752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (fWorkEdge.fPts[0].fY > y) { 1412752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com backup(y); 1413752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 14142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar left = fWorkEdge.fPts[0].fX; 14152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar right = fWorkEdge.fPts[1].fX; 14162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (left > right) { 14172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTSwap(left, right); 14182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1419752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com double ts[2]; 14202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int pts = LineIntersect(fWorkEdge.fPts, left, right, y, ts); 14212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(pts == 1); 14222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // An ActiveEdge or WorkEdge has no need to modify the T values computed 14232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // in the InEdge, except in the following case. If a pair of edges are 14242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // nearly coincident, this may not be detected when the edges are 14252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // intersected. Later, when sorted, and this near-coincidence is found, 14262e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // an additional t value must be added, requiring the cast below. 14272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* writable = const_cast<InEdge*>(fWorkEdge.fEdge); 14282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int insertedAt = writable->add(ts, pts, fWorkEdge.verbIndex()); 1429752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 1430752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d y=%1.9g t=%1.9g\n", __FUNCTION__, ID(), y, ts[0]); 1431752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 14322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (insertedAt >= 0) { 14332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (insertedAt + 1 < fTIndex) { 14342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(insertedAt + 2 == fTIndex); 14352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com --fTIndex; 14362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14396008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 1440cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool advanceT() { 1441198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(fTIndex <= fTs->count() - fExplicitTs); 1442198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return ++fTIndex <= fTs->count() - fExplicitTs; 1443cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 14442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1445cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool advance() { 1446cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // FIXME: flip sense of next 1447cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool result = fWorkEdge.advance(); 1448cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com fDone = !result; 1449cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com initT(); 1450cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return result; 1451cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1452752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1453752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com void backup(SkScalar y) { 1454752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com do { 1455752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkASSERT(fWorkEdge.fEdge->fVerbs.begin() < fWorkEdge.fVerb); 1456752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com fWorkEdge.fPts -= *--fWorkEdge.fVerb; 1457752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkASSERT(fWorkEdge.fEdge->fPts.begin() <= fWorkEdge.fPts); 1458752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } while (fWorkEdge.fPts[0].fY >= y); 1459752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com initT(); 1460198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(!fExplicitTs); 1461752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com fTIndex = fTs->count() + 1; 1462752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 1463752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1464cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com void calcLeft(SkScalar y) { 1465cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // OPTIMIZE: put a kDone_Verb at the end of the verb list? 14664917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (fDone || fBelow.fY > y) { 1467cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return; // nothing to do; use last 14684917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 1469cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com calcLeft(); 1470752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (fAbove.fY == fBelow.fY) { 1471752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d fAbove.fY != fBelow.fY %1.9g\n", __FUNCTION__, 1472752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com ID(), fAbove.fY); 1473752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 1474cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1475752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1476cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com void calcLeft() { 1477a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com void (*xyAtTFunc)(const SkPoint a[], double t, SkPoint* out); 1478cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com switch (fWorkEdge.verb()) { 1479a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 1480a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xyAtTFunc = LineXYAtT; 1481a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1482a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 1483a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xyAtTFunc = QuadXYAtT; 1484a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1485a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 1486a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xyAtTFunc = CubicXYAtT; 1487cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com break; 1488cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com default: 1489cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkASSERT(0); 1490cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1491a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // OPTIMIZATION: if fXAbove, fXBelow have already been computed 1492a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // for the fTIndex, don't do it again 1493a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // For identical x, this lets us know which edge is first. 1494a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // If both edges have T values < 1, check x at next T (fXBelow). 1495198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int add = (fTIndex <= fTs->count() - fExplicitTs) - 1; 1496a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double tAbove = t(fTIndex + add); 1497a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com (*xyAtTFunc)(fWorkEdge.fPts, tAbove, &fAbove); 1498a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double tBelow = t(fTIndex - ~add); 1499a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com (*xyAtTFunc)(fWorkEdge.fPts, tBelow, &fBelow); 1500a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(tAbove != tBelow); 1501a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: this can loop forever 1502a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // need a break if we hit the end 1503198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: in unit test, figure out how explicit Ts work as well 1504a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com while (fAbove.fY == fBelow.fY) { 1505a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (add < 0 || fTIndex == fTs->count()) { 1506a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com add -= 1; 1507a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(fTIndex + add >= 0); 1508a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com tAbove = t(fTIndex + add); 1509a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com (*xyAtTFunc)(fWorkEdge.fPts, tAbove, &fAbove); 1510a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 1511a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com add += 1; 1512a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(fTIndex - ~add <= fTs->count() + 1); 1513a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com tBelow = t(fTIndex - ~add); 1514a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com (*xyAtTFunc)(fWorkEdge.fPts, tBelow, &fBelow); 1515a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1516a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1517a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com #if DEBUG_ABOVE_BELOW 1518a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fTAbove = tAbove; 1519a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fTBelow = tBelow; 1520a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com #endif 15216008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 15226008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 1523752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com bool done(SkScalar bottom) const { 1524752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com return fDone || fYBottom >= bottom; 1525cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1526752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 15272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void fixBelow() { 15282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fFixBelow) { 1529a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (fWorkEdge.verb()) { 1530a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 1531a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(fWorkEdge.fPts, nextT(), &fBelow); 1532a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1533a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 1534a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com QuadXYAtT(fWorkEdge.fPts, nextT(), &fBelow); 1535a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1536a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 1537a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com CubicXYAtT(fWorkEdge.fPts, nextT(), &fBelow); 1538a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1539a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1540a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 1541a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 15422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fFixBelow = false; 15432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 15442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 15452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 15466680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void init(const InEdge* edge) { 15476680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fWorkEdge.init(edge); 15486680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com initT(); 15494917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fBelow.fY = SK_ScalarMin; 1550cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com fDone = false; 1551cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com fYBottom = SK_ScalarMin; 15526680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1553752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 15546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void initT() { 15556008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const Intercepts& intercepts = fWorkEdge.fEdge->fIntercepts.front(); 15566008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkASSERT(fWorkEdge.verbIndex() <= fWorkEdge.fEdge->fIntercepts.count()); 15576008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const Intercepts* interceptPtr = &intercepts + fWorkEdge.verbIndex(); 1558198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTs = &interceptPtr->fTs; 1559198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fExplicitTs = interceptPtr->fExplicit; 15606008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // the above is conceptually the same as 15616008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // fTs = &fWorkEdge.fEdge->fIntercepts[fWorkEdge.verbIndex()].fTs; 15626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // but templated arrays don't allow returning a pointer to the end() element 15636680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fTIndex = 0; 15646680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1565752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1566cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // OPTIMIZATION: record if two edges are coincident when the are intersected 1567cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // It's unclear how to do this -- seems more complicated than recording the 1568cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // t values, since the same t values could exist intersecting non-coincident 1569cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // edges. 1570cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool isCoincidentWith(const ActiveEdge* edge, SkScalar y) const { 1571d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (fAbove != edge->fAbove || fBelow != edge->fBelow) { 1572d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com return false; 1573d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1574cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com uint8_t verb = fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb(); 1575cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com uint8_t edgeVerb = edge->fDone ? edge->fWorkEdge.lastVerb() 1576cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com : edge->fWorkEdge.verb(); 1577cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (verb != edgeVerb) { 1578cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1579cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1580cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com switch (verb) { 1581cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com case SkPath::kLine_Verb: { 15824917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com return true; 1583cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1584cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com default: 1585cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // FIXME: add support for all curve types 1586cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkASSERT(0); 1587cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1588cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return false; 1589cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1590752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 15912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // The shortest close call edge should be moved into a position where 15922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // it contributes if the winding is transitioning to or from zero. 15932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool swapClose(const ActiveEdge* next, int prev, int wind, int mask) const { 1594d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#if DEBUG_ADJUST_COINCIDENT 1595d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkDebugf("%s edge=%d (%g) next=%d (%g) prev=%d wind=%d nextWind=%d\n", 1596d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com __FUNCTION__, ID(), fBelow.fY, next->ID(), next->fBelow.fY, 1597d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com prev, wind, wind + next->fWorkEdge.winding()); 1598d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#endif 15992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((prev & mask) == 0 || (wind & mask) == 0) { 16002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return next->fBelow.fY < fBelow.fY; 16012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 16022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int nextWinding = wind + next->fWorkEdge.winding(); 16032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((nextWinding & mask) == 0) { 16042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fBelow.fY < next->fBelow.fY; 16052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 16062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 16072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1608752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1609cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool swapCoincident(const ActiveEdge* edge, SkScalar bottom) const { 1610cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (fBelow.fY >= bottom || fDone || edge->fDone) { 1611cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1612cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1613cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com ActiveEdge thisWork = *this; 1614cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com ActiveEdge edgeWork = *edge; 1615cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com while ((thisWork.advanceT() || thisWork.advance()) 1616cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && (edgeWork.advanceT() || edgeWork.advance())) { 1617cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com thisWork.calcLeft(); 1618cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com edgeWork.calcLeft(); 1619cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (thisWork < edgeWork) { 1620cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1621cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1622cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (edgeWork < thisWork) { 1623cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return true; 1624cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1625cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1626cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1627cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1628752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 16292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool tooCloseToCall(const ActiveEdge* edge) const { 16302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int ulps; 1631d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // FIXME: the first variation works better (or at least causes fewer tests 1632d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // to fail than the second, although the second's logic better matches the 1633d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // current sort criteria. Need to track down the cause of the crash, and 1634d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // see if the second case isn't somehow buggy. 1635d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#if 01 16362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: don't compare points for equality 16372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // OPTIMIZATION: refactor to make one call to UlpsDiff 16382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge->fAbove.fY - fAbove.fY > fBelow.fY - edge->fAbove.fY 16392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && fBelow.fY < edge->fBelow.fY 16402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com || fAbove.fY - edge->fAbove.fY < edge->fBelow.fY - fAbove.fY 16412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && edge->fBelow.fY < fBelow.fY) { 16422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const SkPoint& check = edge->fBelow.fY <= fBelow.fY 16432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && fBelow != edge->fBelow ? edge->fBelow : 16442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge->fAbove; 16452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ulps = UlpsDiff((check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX), 16462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX)); 16472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } else { 16482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const SkPoint& check = fBelow.fY <= edge->fBelow.fY 16492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && fBelow != edge->fBelow ? fBelow : fAbove; 16502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ulps = UlpsDiff((edge->fBelow.fY - edge->fAbove.fY) 16512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com * (check.fX - edge->fAbove.fX), 16522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (check.fY - edge->fAbove.fY) 16532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com * (edge->fBelow.fX - edge->fAbove.fX)); 16542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1655d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#else 1656d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com double t1, t2, b1, b2; 1657d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (edge->fAbove.fY < fAbove.fY) { 1658d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t1 = (edge->fBelow.fY - edge->fAbove.fY) * (fAbove.fX - edge->fAbove.fX); 1659d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t2 = (fAbove.fY - edge->fAbove.fY) * (edge->fBelow.fX - edge->fAbove.fX); 1660d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else if (edge->fAbove.fY > fAbove.fY) { 1661d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t1 = (fBelow.fY - fAbove.fY) * (fAbove.fX - edge->fAbove.fX); 1662d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t2 = (fAbove.fY - edge->fAbove.fY) * (fBelow.fX - fAbove.fX); 1663d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1664d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t1 = fAbove.fX; 1665d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t2 = edge->fAbove.fX; 1666d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1667d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (edge->fBelow.fY > fBelow.fY) { 1668d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b1 = (edge->fBelow.fY - edge->fAbove.fY) * (fBelow.fX - edge->fBelow.fX); 1669d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b2 = (fBelow.fY - edge->fBelow.fY) * (edge->fBelow.fX - edge->fAbove.fX); 1670d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else if (edge->fBelow.fY < fBelow.fY) { 1671d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b1 = (fBelow.fY - fAbove.fY) * (fBelow.fX - edge->fBelow.fX); 1672d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b2 = (fBelow.fY - edge->fBelow.fY) * (fBelow.fX - fAbove.fX); 1673d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1674d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b1 = fBelow.fX; 1675d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com b2 = edge->fBelow.fX; 1676d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1677d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (fabs(t1 - t2) > fabs(b1 - b2)) { 1678d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com ulps = UlpsDiff(t1, t2); 1679d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1680d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com ulps = UlpsDiff(b1, b2); 1681d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1682d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#if DEBUG_ADJUST_COINCIDENT 1683d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkDebugf("%s this=%d edge=%d ulps=%d\n", __FUNCTION__, ID(), edge->ID(), 1684d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com ulps); 1685d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#endif 1686d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#endif 16872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return ulps >= 0 && ulps <= 32; 16882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1689198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 16902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double nextT() const { 1691198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(fTIndex <= fTs->count() - fExplicitTs); 1692cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return t(fTIndex + 1); 1693cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1694c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1695cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double t() const { 1696198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return t(fTIndex); 1697c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1698c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1699cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double t(int tIndex) const { 1700198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (fExplicitTs) { 1701198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(tIndex < fTs->count()); 1702198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return (*fTs)[tIndex]; 1703198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1704cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (tIndex == 0) { 1705cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return 0; 1706cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1707cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (tIndex > fTs->count()) { 1708cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return 1; 1709cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1710cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return (*fTs)[tIndex - 1]; 1711cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1712cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com 17132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: debugging only 1714752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com int ID() const { 17152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fWorkEdge.fEdge->fID; 17162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 17172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 17182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.compublic: 17196680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com WorkEdge fWorkEdge; 17206680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com const SkTDArray<double>* fTs; 1721cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPoint fAbove; 1722cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPoint fBelow; 17232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ABOVE_BELOW 17242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double fTAbove; 17252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double fTBelow; 17262e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 1727cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar fYBottom; 17282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fCoincident; 17296680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com int fTIndex; 17302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fSkip; // OPTIMIZATION: use bitfields? 17312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fCloseCall; 1732cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool fDone; 17332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fFixBelow; 1734198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fExplicitTs; 1735c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1736c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 17376680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic void addToActive(SkTDArray<ActiveEdge>& activeEdges, const InEdge* edge) { 17386680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com size_t count = activeEdges.count(); 17396680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com for (size_t index = 0; index < count; ++index) { 17406680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com if (edge == activeEdges[index].fWorkEdge.fEdge) { 17416680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return; 17426680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 17436680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 17446680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com ActiveEdge* active = activeEdges.append(); 17456680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com active->init(edge); 17466680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 17476680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 17484917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// Find any intersections in the range of active edges. A pair of edges, on 17494917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// either side of another edge, may change the winding contribution for part of 17504917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// the edge. 17512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// Keep horizontal edges just for 17524917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// the purpose of computing when edges change their winding contribution, since 17534917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// this is essentially computing the horizontal intersection. 17542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic void addBottomT(InEdge** currentPtr, InEdge** lastPtr, 17552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** horizontal) { 17562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** testPtr = currentPtr - 1; 17572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge* horzEdge = *horizontal; 17582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar left = horzEdge->fLeft; 17592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar bottom = horzEdge->fY; 17602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (++testPtr != lastPtr) { 17612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* test = *testPtr; 17622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (test->fBounds.fBottom <= bottom || test->fBounds.fRight <= left) { 17632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 17642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 17652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com WorkEdge wt; 17662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com wt.init(test); 17672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 17682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** sorted = horizontal; 17692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horzEdge = *sorted; 1770f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 1771198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double wtTs[4]; 1772198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int pts; 1773198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t verb = wt.verb(); 1774198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com switch (verb) { 1775198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kLine_Verb: 1776198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = LineIntersect(wt.fPts, horzEdge->fLeft, 1777198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1778198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1779198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kQuad_Verb: 1780198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = QuadIntersect(wt.fPts, horzEdge->fLeft, 1781198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1782198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1783198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kCubic_Verb: 1784198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = CubicIntersect(wt.fPts, horzEdge->fLeft, 1785198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1786198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1787198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1788198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (pts) { 17892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ADD_BOTTOM_TS 1790198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int x = 0; x < pts; ++x) { 1791198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s y=%g wtTs[0]=%g (%g,%g", __FUNCTION__, 1792198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fY, wtTs[x], wt.fPts[0].fX, wt.fPts[0].fY); 1793198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int y = 0; y < verb; ++y) { 1794198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf(" %g,%g", wt.fPts[y + 1].fX, wt.fPts[y + 1].fY)); 17952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1796198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf(")\n"); 1797f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1798198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (pts > verb) { 1799198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(0); // FIXME ? should this work? 1800198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]); 1801198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1802198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 1803198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com test->add(wtTs, pts, wt.verbIndex()); 1804f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 18052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horzEdge = *++sorted; 18062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (horzEdge->fY == bottom 18072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && horzEdge->fLeft <= test->fBounds.fRight); 18082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (wt.advance()); 1809f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1810f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 1811f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 1812a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void debugShowLineIntersection(int pts, const WorkEdge& wt, 1813a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const WorkEdge& wn, const double wtTs[2], const double wnTs[2]) { 1814a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com#if DEBUG_ADD_INTERSECTING_TS 1815a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (!pts) { 1816a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return; 1817a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1818a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint wtOutPt, wnOutPt; 1819a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(wt.fPts, wtTs[0], &wtOutPt); 1820a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(wn.fPts, wnTs[0], &wnOutPt); 1821fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s wtTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n", 1822a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com __FUNCTION__, 1823a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com wtTs[0], wt.fPts[0].fX, wt.fPts[0].fY, 1824fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com wt.fPts[1].fX, wt.fPts[1].fY, wtOutPt.fX, wtOutPt.fY); 1825a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (pts == 2) { 1826a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]); 1827a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1828fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s wnTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n", 1829a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com __FUNCTION__, 1830a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com wnTs[0], wn.fPts[0].fX, wn.fPts[0].fY, 1831fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com wn.fPts[1].fX, wn.fPts[1].fY, wnOutPt.fX, wnOutPt.fY); 1832a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (pts == 2) { 1833a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkDebugf("%s wnTs[1]=%g\n", __FUNCTION__, wnTs[1]); 1834a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1835a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com#endif 1836a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 1837a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 1838f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) { 1839cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge** testPtr = currentPtr - 1; 1840752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // FIXME: lastPtr should be past the point of interest, so 1841752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // test below should be lastPtr - 2 1842752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // that breaks testSimplifyTriangle22, so further investigation is needed 1843cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com while (++testPtr != lastPtr - 1) { 1844cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge* test = *testPtr; 1845cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge** nextPtr = testPtr; 1846cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com do { 1847cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge* next = *++nextPtr; 1848198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: this compares against the sentinel sometimes 1849198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: this may never be needed since this gets called 1850198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // in two passes now. Verify that double hits are appropriate. 1851cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (test->cached(next)) { 1852cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com continue; 1853cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1854cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (!Bounds::Intersects(test->fBounds, next->fBounds)) { 1855cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com continue; 1856cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1857f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com WorkEdge wt, wn; 1858f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wt.init(test); 1859f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wn.init(next); 1860f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 1861a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com int pts; 1862a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections ts; 1863a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bool swap = false; 1864a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wt.verb()) { 1865a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 1866a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 1867a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 1868a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = LineIntersect(wt.fPts, wn.fPts, ts); 1869a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com debugShowLineIntersection(pts, wt, wn, 1870a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com ts.fT[0], ts.fT[1]); 1871a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1872a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1873a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 1874a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com swap = true; 1875a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadLineIntersect(wn.fPts, wt.fPts, ts); 1876a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1877a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1878a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 1879a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com swap = true; 1880a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicLineIntersect(wn.fPts, wt.fPts, ts); 1881a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1882a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1883a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1884a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 18852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1886a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1887a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 1888a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 1889a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 1890a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadLineIntersect(wt.fPts, wn.fPts, ts); 1891a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1892a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1893a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 1894a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadIntersect(wt.fPts, wn.fPts, ts); 1895a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1896a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1897a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 1898a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: promote quad to cubic 1899a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 1900a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1901a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1902a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1903a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 19042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1905a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1906a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 1907a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 1908a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 1909a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicLineIntersect(wt.fPts, wn.fPts, ts); 1910a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1911a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1912a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 1913a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: promote quad to cubic 1914a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 1915a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1916a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1917a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 1918a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 1919a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1920a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1921a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1922a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 1923a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1924a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1925a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1926a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 1927f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1928a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com test->add(ts.fT[swap], pts, wt.verbIndex()); 1929a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com next->add(ts.fT[!swap], pts, wn.verbIndex()); 1930cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (wt.bottom() <= wn.bottom() ? wt.advance() : wn.advance()); 1931cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (nextPtr != lastPtr); 1932f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1933f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 1934f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 19352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic InEdge** advanceEdges(SkTDArray<ActiveEdge>* activeEdges, 19366008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge** currentPtr, InEdge** lastPtr, SkScalar y) { 19376008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge** testPtr = currentPtr - 1; 19386008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (++testPtr != lastPtr) { 19396008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if ((*testPtr)->fBounds.fBottom > y) { 19406008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com continue; 19416008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 19422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdges) { 19432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* test = *testPtr; 19442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* activePtr = activeEdges->begin() - 1; 19452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* lastActive = activeEdges->end(); 19462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (++activePtr != lastActive) { 19472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fWorkEdge.fEdge == test) { 19482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdges->remove(activePtr - activeEdges->begin()); 19492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com break; 19502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 19516008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 19526008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 19536008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (testPtr == currentPtr) { 19546008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++currentPtr; 19556008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 19566008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 19576008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return currentPtr; 19586008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com} 19596008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 19602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZE: inline? 19612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic HorizontalEdge** advanceHorizontal(HorizontalEdge** edge, SkScalar y) { 19622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while ((*edge)->fY < y) { 19632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ++edge; 19642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 19652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return edge; 19662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 19672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1968f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com// compute bottom taking into account any intersected edges 19692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic SkScalar computeInterceptBottom(SkTDArray<ActiveEdge>& activeEdges, 19702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y, SkScalar bottom) { 1971f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ActiveEdge* activePtr = activeEdges.begin() - 1; 1972f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ActiveEdge* lastActive = activeEdges.end(); 1973f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com while (++activePtr != lastActive) { 1974f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const InEdge* test = activePtr->fWorkEdge.fEdge; 1975f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com if (!test->fContainsIntercepts) { 1976f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com continue; 1977f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1978f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com WorkEdge wt; 1979f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wt.init(test); 1980f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 1981f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const Intercepts& intercepts = test->fIntercepts[wt.verbIndex()]; 19824917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (intercepts.fTopIntercepts > 1) { 19834917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com SkScalar yTop = wt.fPts[0].fY; 19844917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (yTop > y && bottom > yTop) { 19854917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com bottom = yTop; 19864917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 19874917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 19884917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (intercepts.fBottomIntercepts > 1) { 19894917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com SkScalar yBottom = wt.fPts[wt.verb()].fY; 19904917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (yBottom > y && bottom > yBottom) { 19914917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com bottom = yBottom; 19924917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 19934917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 1994f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const SkTDArray<double>& fTs = intercepts.fTs; 1995f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t count = fTs.count(); 1996f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com for (size_t index = 0; index < count; ++index) { 1997a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkScalar yIntercept; 1998a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wt.verb()) { 1999a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 2000a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = LineYAtT(wt.fPts, fTs[index]); 2001a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2002f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2003a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 2004a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = QuadYAtT(wt.fPts, fTs[index]); 2005a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2006a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2007a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 2008a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = CubicYAtT(wt.fPts, fTs[index]); 2009a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2010a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2011a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2012a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); // should never get here 2013a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2014a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (yIntercept > y && bottom > yIntercept) { 2015a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bottom = yIntercept; 2016f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2017f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2018cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (wt.advance()); 2019f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2020198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#if DEBUG_BOTTOM 2021198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s bottom=%1.9g\n", __FUNCTION__, bottom); 2022198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 20232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 2024f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2025f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 2026f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic SkScalar findBottom(InEdge** currentPtr, 20272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** edgeListEnd, SkTDArray<ActiveEdge>* activeEdges, SkScalar y, 20286008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool asFill, InEdge**& testPtr) { 2029f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge* current = *currentPtr; 2030f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar bottom = current->fBounds.fBottom; 2031752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 2032f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // find the list of edges that cross y 20336008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge* test = *testPtr; 20346008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (testPtr != edgeListEnd) { 20356008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkScalar testTop = test->fBounds.fTop; 20366008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (bottom <= testTop) { 2037f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com break; 2038f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 20396008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkScalar testBottom = test->fBounds.fBottom; 2040f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // OPTIMIZATION: Shortening the bottom is only interesting when filling 2041f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // and when the edge is to the left of a longer edge. If it's a framing 2042f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // edge, or part of the right, it won't effect the longer edges. 20436008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (testTop > y) { 20446008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bottom = testTop; 20456008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com break; 20466008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (y < testBottom) { 20486008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (bottom > testBottom) { 20496008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bottom = testBottom; 2050f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 20512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdges) { 20522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addToActive(*activeEdges, test); 20532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 2054f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 20556008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com test = *++testPtr; 2056f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2057198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#if DEBUG_BOTTOM 2058198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s %d bottom=%1.9g\n", __FUNCTION__, activeEdges ? 2 : 1, bottom); 2059198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 2060f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return bottom; 2061f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2062f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 2063f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic void makeEdgeList(SkTArray<InEdge>& edges, InEdge& edgeSentinel, 2064f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<InEdge*>& edgeList) { 2065c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t edgeCount = edges.count(); 2066c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edgeCount == 0) { 2067c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 2068c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 2069fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int id = 0; 2070c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < edgeCount; ++index) { 2071fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com InEdge& edge = edges[index]; 2072fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (!edge.fWinding) { 2073fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com continue; 2074fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 2075fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge.fID = ++id; 2076fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edgeList.append() = &edge; 2077c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 2078c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *edgeList.append() = &edgeSentinel; 2079cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com QSort<InEdge>(edgeList.begin(), edgeList.end() - 1); 2080f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2081f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 20822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic void makeHorizontalList(SkTDArray<HorizontalEdge>& edges, 20832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge& edgeSentinel, SkTDArray<HorizontalEdge*>& edgeList) { 20842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t edgeCount = edges.count(); 20852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edgeCount == 0) { 20862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 20872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 20882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (size_t index = 0; index < edgeCount; ++index) { 20892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *edgeList.append() = &edges[index]; 20902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 20912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edgeSentinel.fLeft = edgeSentinel.fRight = edgeSentinel.fY = SK_ScalarMax; 20922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *edgeList.append() = &edgeSentinel; 20932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com QSort<HorizontalEdge>(edgeList.begin(), edgeList.end() - 1); 20942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 20956b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com 20966b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.comstatic void skipCoincidence(int lastWinding, int winding, int windingMask, 20976b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com ActiveEdge* activePtr, ActiveEdge* firstCoincident) { 20986b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (((lastWinding & windingMask) == 0) ^ (winding & windingMask) != 0) { 20996b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com return; 21006b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 21012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: ? shouldn't this be if (lastWinding & windingMask) ? 21026b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (lastWinding) { 2103752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 2104752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d 1 set skip=false\n", __FUNCTION__, activePtr->ID()); 2105752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#endif 21066b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com activePtr->fSkip = false; 21076b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } else { 2108752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 2109752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d 2 set skip=false\n", __FUNCTION__, firstCoincident->ID()); 2110752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#endif 21116b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident->fSkip = false; 21126b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 21136b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com} 21146b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com 21156008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.comstatic void sortHorizontal(SkTDArray<ActiveEdge>& activeEdges, 21162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<ActiveEdge*>& edgeList, SkScalar y) { 21176008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t edgeCount = activeEdges.count(); 21186008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (edgeCount == 0) { 21196008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return; 21206008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 21212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 2122d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com const int tab = 3; // FIXME: debugging only 21232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s y=%1.9g\n", __FUNCTION__, y); 21242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 21256008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t index; 21266008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 0; index < edgeCount; ++index) { 21276008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge& activeEdge = activeEdges[index]; 21282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 21292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.calcLeft(y); 21302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // skip segments that don't span y 21312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdge.fAbove != activeEdge.fBelow) { 21322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com break; 21332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdge.fDone) { 21352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 21362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d done\n", tab, "", activeEdge.ID()); 21372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 21382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com goto nextEdge; 21392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 21412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d above==below\n", tab, "", activeEdge.ID()); 21422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 21432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (activeEdge.advanceT() || activeEdge.advance()); 21442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 21452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d above=(%1.9g,%1.9g) (%1.9g) below=(%1.9g,%1.9g)" 21462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com " (%1.9g)\n", tab, "", activeEdge.ID(), 21472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fAbove.fX, activeEdge.fAbove.fY, activeEdge.fTAbove, 21482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fBelow.fX, activeEdge.fBelow.fY, activeEdge.fTBelow); 21492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 21502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fSkip = activeEdge.fCloseCall = activeEdge.fFixBelow = false; 21516008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com *edgeList.append() = &activeEdge; 21522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comnextEdge: 21532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ; 21546008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 2155cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com QSort<ActiveEdge>(edgeList.begin(), edgeList.end() - 1); 21562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 21572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 21582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// remove coincident edges 21592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZE: remove edges? This is tricky because the current logic expects 21602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// the winding count to be maintained while skipping coincident edges. In 21612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// addition to removing the coincident edges, the remaining edges would need 21622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// to have a different winding value, possibly different per intercept span. 21632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic SkScalar adjustCoincident(SkTDArray<ActiveEdge*>& edgeList, 21642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int windingMask, SkScalar y, SkScalar bottom, OutEdgeBuilder& outBuilder) 21652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com{ 21662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 21672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom); 21682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 21692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t edgeCount = edgeList.count(); 21702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edgeCount == 0) { 21712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 21722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21736008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge* activePtr = edgeList[0]; 21742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t index; 21752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool foundCoincident = false; 21762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int firstIndex = 0; 21772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 1; index < edgeCount; ++index) { 21782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* nextPtr = edgeList[index]; 21792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool closeCall = false; 21802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fCoincident = firstIndex; 21812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->isCoincidentWith(nextPtr, y) 21822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com || (closeCall = activePtr->tooCloseToCall(nextPtr))) { 21832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fSkip = nextPtr->fSkip = foundCoincident = true; 21842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fCloseCall = nextPtr->fCloseCall = closeCall; 21852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } else { 21862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com firstIndex = index; 21872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr = nextPtr; 21892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fCoincident = firstIndex; 21912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (!foundCoincident) { 21922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 21932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21946b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com int winding = 0; 21952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr = edgeList[0]; 21966008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 1; index < edgeCount; ++index) { 21972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int priorWinding = winding; 21986b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com winding += activePtr->fWorkEdge.winding(); 21996008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge* nextPtr = edgeList[index]; 22002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCoincident == nextPtr->fCoincident) { 2201cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // the coincident edges may not have been sorted above -- advance 2202cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // the edges and resort if needed 2203cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // OPTIMIZE: if sorting is done incrementally as new edges are added 2204cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // and not all at once as is done here, fold this test into the 2205cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // current less than test. 22062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCloseCall ? activePtr->swapClose(nextPtr, 22072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com priorWinding, winding, windingMask) 22082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com : activePtr->swapCoincident(nextPtr, bottom)) { 22094917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com winding -= activePtr->fWorkEdge.winding(); 2210cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]); 2211cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkTSwap<ActiveEdge*>(activePtr, nextPtr); 22124917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com winding += activePtr->fWorkEdge.winding(); 2213cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 22142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr = nextPtr; 22162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int firstCoincidentWinding = 0; 22182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* firstCoincident = NULL; 22192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com winding = 0; 22202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr = edgeList[0]; 22212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 1; index < edgeCount; ++index) { 22222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int priorWinding = winding; 22232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com winding += activePtr->fWorkEdge.winding(); 22242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* nextPtr = edgeList[index]; 22252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCoincident == nextPtr->fCoincident) { 22266b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (!firstCoincident) { 22276b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident = activePtr; 22282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com firstCoincidentWinding = priorWinding; 22292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCloseCall) { 22312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // If one of the edges has already been added to out as a non 22322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // coincident edge, trim it back to the top of this span 22332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (outBuilder.trimLine(y, activePtr->ID())) { 22342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->addTatYAbove(y); 2235752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2236752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 1 edge=%d y=%1.9g (was fYBottom=%1.9g)\n", 2237752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, activePtr->ID(), y, activePtr->fYBottom); 2238752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 22392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fYBottom = y; 22402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (outBuilder.trimLine(y, nextPtr->ID())) { 22422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->addTatYAbove(y); 2243752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2244752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 2 edge=%d y=%1.9g (was fYBottom=%1.9g)\n", 2245752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, nextPtr->ID(), y, nextPtr->fYBottom); 2246752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 22472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->fYBottom = y; 22482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // add missing t values so edges can be the same length 22502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar testY = activePtr->fBelow.fY; 22512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->addTatYBelow(testY); 22522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (bottom > testY && testY > y) { 2253752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2254752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 3 edge=%d bottom=%1.9g (was bottom=%1.9g)\n", 2255752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, activePtr->ID(), testY, bottom); 2256752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 22572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = testY; 22582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com testY = nextPtr->fBelow.fY; 22602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->addTatYBelow(testY); 22612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (bottom > testY && testY > y) { 2262752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2263752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 4 edge=%d bottom=%1.9g (was bottom=%1.9g)\n", 2264752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, nextPtr->ID(), testY, bottom); 2265752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 22662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = testY; 22672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22686b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 22692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } else if (firstCoincident) { 22702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com skipCoincidence(firstCoincidentWinding, winding, windingMask, 22712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr, firstCoincident); 22726b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident = NULL; 22736b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 22746008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com activePtr = nextPtr; 2275f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 22762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (firstCoincident) { 22776b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com winding += activePtr->fWorkEdge.winding(); 22782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com skipCoincidence(firstCoincidentWinding, winding, windingMask, activePtr, 22796b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident); 22806b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 22812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fix up the bottom for close call edges. OPTIMIZATION: maybe this could 22822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // be in the loop above, but moved here since loop above reads fBelow and 22832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // it felt unsafe to write it in that loop 22842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 0; index < edgeCount; ++index) { 22852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (edgeList[index])->fixBelow(); 22862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 2288f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 22896680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 2290f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com// stitch edge and t range that satisfies operation 22916008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.comstatic void stitchEdge(SkTDArray<ActiveEdge*>& edgeList, SkScalar y, 2292752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkScalar bottom, int windingMask, bool fill, OutEdgeBuilder& outBuilder) { 2293f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int winding = 0; 22946008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge** activeHandle = edgeList.begin() - 1; 22956008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge** lastActive = edgeList.end(); 22962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 7; // FIXME: debugging only 2297cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (gShowDebugf) { 22982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom); 2299c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com } 23006008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (++activeHandle != lastActive) { 23016008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge* activePtr = *activeHandle; 2302f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const WorkEdge& wt = activePtr->fWorkEdge; 2303f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int lastWinding = winding; 2304f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com winding += wt.winding(); 23052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (gShowDebugf) { 23062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d lastWinding=%d winding=%d skip=%d close=%d" 23072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ABOVE_BELOW 23082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com " above=%1.9g below=%1.9g" 23092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 23102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com "\n", 23112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com tab-4, "", activePtr->ID(), lastWinding, 23122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com winding, activePtr->fSkip, activePtr->fCloseCall 23132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ABOVE_BELOW 23142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com , activePtr->fTAbove, activePtr->fTBelow 23152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 23162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ); 23172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 2318752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (activePtr->done(bottom)) { 2319752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (gShowDebugf) { 2320752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s fDone=%d || fYBottom=%1.9g >= bottom\n", tab, "", 2321752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com activePtr->fDone, activePtr->fYBottom); 2322cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 2323752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com continue; 2324cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 2325c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com int opener = (lastWinding & windingMask) == 0; 2326c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com bool closer = (winding & windingMask) == 0; 2327c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com SkASSERT(!opener | !closer); 2328c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com bool inWinding = opener | closer; 2329a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint clippedPts[4]; 23304917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com const SkPoint* clipped = NULL; 2331cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com uint8_t verb = wt.verb(); 2332cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool moreToDo, aboveBottom; 2333f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 2334f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com double currentT = activePtr->t(); 2335f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const SkPoint* points = wt.fPts; 2336cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double nextT; 23376680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com do { 2338cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com nextT = activePtr->nextT(); 2339a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: obtuse: want efficient way to say 2340a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // !currentT && currentT != 1 || !nextT && nextT != 1 2341a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (currentT * nextT != 0 || currentT + nextT != 1) { 2342a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // OPTIMIZATION: if !inWinding, we only need 2343a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // clipped[1].fY 2344a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (verb) { 2345a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 2346a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineSubDivide(points, currentT, nextT, clippedPts); 2347a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2348a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 2349a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com QuadSubDivide(points, currentT, nextT, clippedPts); 2350a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2351a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 2352a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com CubicSubDivide(points, currentT, nextT, clippedPts); 2353a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2354a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2355a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 2356a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 23576680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 2358a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com clipped = clippedPts; 2359a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 2360a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com clipped = points; 2361a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2362a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (inWinding && !activePtr->fSkip && (fill ? clipped[0].fY 2363a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com != clipped[verb].fY : clipped[0] != clipped[verb])) { 2364fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 2365fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s add%s %1.9g,%1.9g %1.9g,%1.9g edge=%d" 2366fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com " v=%d t=(%1.9g,%1.9g)\n", tab, "", 2367fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kUVerbStr[verb], clipped[0].fX, clipped[0].fY, 2368fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com clipped[verb].fX, clipped[verb].fY, 2369fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->ID(), 2370fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->fWorkEdge.fVerb 2371fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com - activePtr->fWorkEdge.fEdge->fVerbs.begin(), 2372fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com currentT, nextT); 2373fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 2374a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com outBuilder.addCurve(clipped, (SkPath::Verb) verb, 2375a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fWorkEdge.fEdge->fID, 2376a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fCloseCall); 2377cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } else { 2378fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 2379fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s skip%s %1.9g,%1.9g %1.9g,%1.9g" 2380fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com " edge=%d v=%d t=(%1.9g,%1.9g)\n", tab, "", 2381fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kUVerbStr[verb], clipped[0].fX, clipped[0].fY, 2382fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com clipped[verb].fX, clipped[verb].fY, 2383fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->ID(), 2384fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->fWorkEdge.fVerb 2385fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com - activePtr->fWorkEdge.fEdge->fVerbs.begin(), 2386fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com currentT, nextT); 2387fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 2388a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2389a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // by advancing fAbove/fBelow, the next call to sortHorizontal 2390a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // will use these values if they're still valid instead of 2391a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // recomputing 2392a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (clipped[1].fY > activePtr->fBelow.fY 2393a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com && bottom >= activePtr->fBelow.fY ) { 2394a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fAbove = activePtr->fBelow; 2395a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fBelow = clipped[1]; 2396a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com #if DEBUG_ABOVE_BELOW 2397a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fTAbove = activePtr->fTBelow; 2398a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fTBelow = nextT; 2399a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com #endif 2400f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2401f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com currentT = nextT; 2402cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com moreToDo = activePtr->advanceT(); 24032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fYBottom = clipped[verb].fY; // was activePtr->fCloseCall ? bottom : 24042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 24052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // clearing the fSkip/fCloseCall bit here means that trailing edges 24062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fall out of sync, if one edge is long and another is a series of short pieces 24072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // if fSkip/fCloseCall is set, need to recompute coincidence/too-close-to-call 24082e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // after advancing 24092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // another approach would be to restrict bottom to smaller part of close call 24102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // maybe this is already happening with coincidence when intersection is computed, 24112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // and needs to be added to the close call computation as well 24122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // this is hard to do because that the bottom is important is not known when 24132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // the lines are intersected; only when the computation for edge sorting is done 24142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // does the need for new bottoms become apparent. 24152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // maybe this is good incentive to scrap the current sort and do an insertion 24162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // sort that can take this into consideration when the x value is computed 24172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 24182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: initialized in sortHorizontal, cleared here as well so 24192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // that next edge is not skipped -- but should skipped edges ever 24202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // continue? (probably not) 2421752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com aboveBottom = clipped[verb].fY < bottom; 2422752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (clipped[0].fY != clipped[verb].fY) { 2423752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com activePtr->fSkip = false; 2424752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com activePtr->fCloseCall = false; 2425752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com aboveBottom &= !activePtr->fCloseCall; 2426752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } else { 2427752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (activePtr->fSkip || activePtr->fCloseCall) { 2428198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (gShowDebugf) SkDebugf("== %1.9g\n", clippedPts[0].fY); 2429752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 2430752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 2431cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (moreToDo & aboveBottom); 2432cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while ((moreToDo || activePtr->advance()) & aboveBottom); 2433f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2434f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 24356680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 2436198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic void dumpEdgeList(const SkTDArray<InEdge*>& edgeList, 2437198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const InEdge& edgeSentinel) { 2438198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#if DEBUG_DUMP 2439198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge** debugPtr = edgeList.begin(); 2440198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com do { 2441198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com (*debugPtr++)->dump(); 2442198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } while (*debugPtr != &edgeSentinel); 2443198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 2444198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 2445198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 2446f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comvoid simplify(const SkPath& path, bool asFill, SkPath& simple) { 2447f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // returns 1 for evenodd, -1 for winding, regardless of inverse-ness 2448f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int windingMask = (path.getFillType() & 1) ? 1 : -1; 2449f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com simple.reset(); 2450f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com simple.setFillType(SkPath::kEvenOdd_FillType); 2451f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // turn path into list of edges increasing in y 2452cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if an edge is a quad or a cubic with a y extrema, note it, but leave it 2453cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // unbroken. Once we have a list, sort it, then walk the list (walk edges 2454cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // twice that have y extrema's on top) and detect crossings -- look for raw 2455cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // bounds that cross over, then tight bounds that cross 2456f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTArray<InEdge> edges; 24572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge> horizontalEdges; 24582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdgeBuilder builder(path, asFill, edges, horizontalEdges); 2459f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<InEdge*> edgeList; 2460f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge edgeSentinel; 2461fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edgeSentinel.reset(); 2462f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com makeEdgeList(edges, edgeSentinel, edgeList); 24632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge*> horizontalList; 24642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge horizontalSentinel; 24652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com makeHorizontalList(horizontalEdges, horizontalSentinel, horizontalList); 2466f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge** currentPtr = edgeList.begin(); 24674917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (!currentPtr) { 24684917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com return; 24694917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 24702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // find all intersections between edges 24712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// beyond looking for horizontal intercepts, we need to know if any active edges 24722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// intersect edges below 'bottom', but above the active edge segment. 24732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// maybe it makes more sense to compute all intercepts before doing anything 24742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// else, since the intercept list is long-lived, at least in the current design. 24752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y = (*currentPtr)->fBounds.fTop; 24762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** currentHorizontal = horizontalList.begin(); 24772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 24782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set 24792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar bottom = findBottom(currentPtr, edgeList.end(), 24802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com NULL, y, asFill, lastPtr); 24812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (lastPtr > currentPtr) { 24822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (currentHorizontal) { 24832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((*currentHorizontal)->fY < SK_ScalarMax) { 24842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addBottomT(currentPtr, lastPtr, currentHorizontal); 24852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentHorizontal = advanceHorizontal(currentHorizontal, bottom); 24872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addIntersectingTs(currentPtr, lastPtr); 24892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com y = bottom; 24912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = advanceEdges(NULL, currentPtr, lastPtr, y); 24922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (*currentPtr != &edgeSentinel); 2493198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // if a quadratic or cubic now has an intermediate T value, see if the Ts 2494198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // on either side cause the Y values to monotonically increase. If not, split 2495198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // the curve at the new T. 2496198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (builder.containsCurves()) { 2497198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com currentPtr = edgeList.begin(); 2498198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTArray<InEdge> splits; 2499198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com do { 2500fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com (*currentPtr)->splitInflectionPts(splits); 2501198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } while (*++currentPtr != &edgeSentinel); 2502198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (splits.count()) { 2503198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int index = 0; index < splits.count(); ++index) { 2504198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edges.push_back(splits[index]); 2505198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2506fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edgeList.reset(); 2507198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com makeEdgeList(edges, edgeSentinel, edgeList); 2508198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2509198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2510198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com dumpEdgeList(edgeList, edgeSentinel); 2511f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // walk the sorted edges from top to bottom, computing accumulated winding 2512f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<ActiveEdge> activeEdges; 2513f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com OutEdgeBuilder outBuilder(asFill); 25142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = edgeList.begin(); 25152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com y = (*currentPtr)->fBounds.fTop; 2516f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 2517f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set 2518f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar bottom = findBottom(currentPtr, edgeList.end(), 25192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com &activeEdges, y, asFill, lastPtr); 2520c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com if (lastPtr > currentPtr) { 25212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = computeInterceptBottom(activeEdges, y, bottom); 2522c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com SkTDArray<ActiveEdge*> activeEdgeList; 25232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com sortHorizontal(activeEdges, activeEdgeList, y); 25242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = adjustCoincident(activeEdgeList, windingMask, y, bottom, 25252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com outBuilder); 2526752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com stitchEdge(activeEdgeList, y, bottom, windingMask, asFill, outBuilder); 2527c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com } 2528c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com y = bottom; 25292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // OPTIMIZATION: as edges expire, InEdge allocations could be released 25302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = advanceEdges(&activeEdges, currentPtr, lastPtr, y); 2531c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } while (*currentPtr != &edgeSentinel); 2532c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // assemble output path from string of pts, verbs 2533f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com outBuilder.bridge(); 2534f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com outBuilder.assemble(simple); 2535c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 2536