EdgeWalker.cpp revision 47d73daa7a971e7eee5822def7922f7d43b2dc47
1c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com/* 2c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * Copyright 2012 Google Inc. 3c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * 4c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be 5c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com * found in the LICENSE file. 6c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com */ 7c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 88dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com#include "Simplify.h" 9c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#undef SkASSERT 1178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define SkASSERT(cond) while (!(cond)) { sk_throw(); } 122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com// FIXME: remove once debugging is complete 14fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com#if 01 // set to 1 for no debugging whatsoever 1578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 1647580694fbe974a065caf7c39c3d2075708c2018caryclark@google.com//const bool gRunTestsInOneThread = false; 1778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 1878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ACTIVE_LESS_THAN 0 192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD 0 202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_BOTTOM_TS 0 2178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ADD_INTERSECTING_TS 0 2278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ADJUST_COINCIDENT 0 23fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_ASSEMBLE 0 2478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_BOTTOM 0 25fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_BRIDGE 0 2678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_DUMP 0 272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_SORT_HORIZONTAL 0 282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT 0 292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT_LESS_THAN 0 30198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#define DEBUG_SPLIT 0 31fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_STITCH_EDGE 0 3278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_TRIM_LINE 0 3378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#else 352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 3647580694fbe974a065caf7c39c3d2075708c2018caryclark@google.com//const bool gRunTestsInOneThread = true; 3778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 3878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ACTIVE_LESS_THAN 0 392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD 01 402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_ADD_BOTTOM_TS 0 4178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ADD_INTERSECTING_TS 0 4278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_ADJUST_COINCIDENT 1 43fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_ASSEMBLE 1 4478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_BOTTOM 0 45fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_BRIDGE 1 4678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_DUMP 1 472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_SORT_HORIZONTAL 01 482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT 01 492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#define DEBUG_OUT_LESS_THAN 0 50198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#define DEBUG_SPLIT 1 51fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#define DEBUG_STITCH_EDGE 1 5278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define DEBUG_TRIM_LINE 1 53752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 56fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE || DEBUG_BRIDGE 57fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic const char* kLVerbStr[] = {"", "line", "quad", "cubic"}; 58fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 59fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 60fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"}; 61fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 62fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 636680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic int LineIntersect(const SkPoint a[2], const SkPoint b[2], 64a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 65a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 66a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 6745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com return intersect(aLine, bLine, intersections); 68a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 69a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 70a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2], 71a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 72a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 73a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 74198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intersect(aQuad, bLine, intersections); 75198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 76a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 77a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 78a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int CubicLineIntersect(const SkPoint a[2], const SkPoint b[3], 79a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 80a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 81a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 82a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}}; 8373ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com return intersect(aCubic, bLine, intersections); 84a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 85a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 86a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int QuadIntersect(const SkPoint a[3], const SkPoint b[3], 87a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 88a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 89a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic bQuad = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}}; 9045a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com intersect2(aQuad, bQuad, intersections); 91198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 92a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 93a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 94a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic int CubicIntersect(const SkPoint a[4], const SkPoint b[4], 95a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections& intersections) { 96a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 97a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 98a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic bCubic = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}, 99a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {b[3].fX, b[3].fY}}; 100198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intersect(aCubic, bCubic, intersections); 101198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return intersections.fUsed; 102c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 103c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic int LineIntersect(const SkPoint a[2], SkScalar left, SkScalar right, 1052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y, double aRange[2]) { 106a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return horizontalLineIntersect(aLine, left, right, y, aRange); 108c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 109c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 110198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic int QuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right, 111198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y, double aRange[3]) { 112198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 113198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return horizontalIntersect(aQuad, left, right, y, aRange); 114198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 115198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 116198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic int CubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right, 117198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y, double aRange[4]) { 118198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 119198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com {a[3].fX, a[3].fY}}; 120198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return horizontalIntersect(aCubic, left, right, y, aRange); 121198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 122198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 123cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.comstatic void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) { 124a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line line = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 125cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com double x, y; 126a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(line, t, x, y); 127cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com out->fX = SkDoubleToScalar(x); 128cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com out->fY = SkDoubleToScalar(y); 129cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com} 130cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com 131a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) { 132a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 133a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double x, y; 134a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(quad, t, x, y); 135a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fX = SkDoubleToScalar(x); 136a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fY = SkDoubleToScalar(y); 1372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 139a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) { 140a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 141a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 142a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double x, y; 143a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(cubic, t, x, y); 144a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fX = SkDoubleToScalar(x); 145a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com out->fY = SkDoubleToScalar(y); 1462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1486680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic SkScalar LineYAtT(const SkPoint a[2], double t) { 149a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1506680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com double y; 1516680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com xy_at_t(aLine, t, *(double*) 0, y); 1526680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return SkDoubleToScalar(y); 1536680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 1546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 155a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic SkScalar QuadYAtT(const SkPoint a[3], double t) { 156a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}}; 157a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double y; 158a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(quad, t, *(double*) 0, y); 159a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return SkDoubleToScalar(y); 160a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 161a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 162a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic SkScalar CubicYAtT(const SkPoint a[4], double t) { 163a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}, 164a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com {a[3].fX, a[3].fY}}; 165a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double y; 166a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com xy_at_t(cubic, t, *(double*) 0, y); 167a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return SkDoubleToScalar(y); 168a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 169a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 1706680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic void LineSubDivide(const SkPoint a[2], double startT, double endT, 1716680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkPoint sub[2]) { 172a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 1736680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com _Line dst; 1746680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub_divide(aLine, startT, endT, dst); 1756680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 1766680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 1776680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 1786680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 1796680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 1806680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 181a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void QuadSubDivide(const SkPoint a[3], double startT, double endT, 182a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint sub[3]) { 18378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, 18478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com {a[2].fX, a[2].fY}}; 185a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Quadratic dst; 186a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub_divide(aQuad, startT, endT, dst); 187a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 188a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 189a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 190a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 191a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fX = SkDoubleToScalar(dst[2].x); 192a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fY = SkDoubleToScalar(dst[2].y); 1932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 1946680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 195a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void CubicSubDivide(const SkPoint a[4], double startT, double endT, 196a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint sub[4]) { 19778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, 19878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com {a[2].fX, a[2].fY}, {a[3].fX, a[3].fY}}; 199a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Cubic dst; 200a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub_divide(aCubic, startT, endT, dst); 201a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fX = SkDoubleToScalar(dst[0].x); 202a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[0].fY = SkDoubleToScalar(dst[0].y); 203a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fX = SkDoubleToScalar(dst[1].x); 204a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[1].fY = SkDoubleToScalar(dst[1].y); 205a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fX = SkDoubleToScalar(dst[2].x); 206a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[2].fY = SkDoubleToScalar(dst[2].y); 207a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[3].fX = SkDoubleToScalar(dst[3].x); 208a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com sub[3].fY = SkDoubleToScalar(dst[3].y); 209a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 210fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 211fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic void QuadSubBounds(const SkPoint a[3], double startT, double endT, 212fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkRect& bounds) { 213fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint dst[3]; 214fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com QuadSubDivide(a, startT, endT, dst); 215fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fLeft = bounds.fRight = dst[0].fX; 216fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fTop = bounds.fBottom = dst[0].fY; 217fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 1; index < 3; ++index) { 218fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.growToInclude(dst[index].fX, dst[index].fY); 219fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 220fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com} 221fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 222fb173424e915e696a73067d616ce4f39a407261acaryclark@google.comstatic void CubicSubBounds(const SkPoint a[4], double startT, double endT, 223fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkRect& bounds) { 224fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint dst[4]; 225fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com CubicSubDivide(a, startT, endT, dst); 226fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fLeft = bounds.fRight = dst[0].fX; 227fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.fTop = bounds.fBottom = dst[0].fY; 228fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 1; index < 4; ++index) { 229fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bounds.growToInclude(dst[index].fX, dst[index].fY); 230fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 231fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com} 232fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com 23378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comstatic SkPath::Verb QuadReduceOrder(SkPoint a[4]) { 23478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, 23578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com {a[2].fX, a[2].fY}}; 23678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com Quadratic dst; 23747d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com int order = reduceOrder(aQuad, dst, kReduceOrder_TreatAsFill); 23878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com for (int index = 0; index < order; ++index) { 23978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[index].fX = SkDoubleToScalar(dst[index].x); 24078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[index].fY = SkDoubleToScalar(dst[index].y); 24178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 24278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (order == 1) { // FIXME: allow returning points, caller should discard 24378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[1] = a[0]; 24478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return (SkPath::Verb) order; 24578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 24678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return (SkPath::Verb) (order - 1); 24778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com} 24878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 24978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comstatic SkPath::Verb CubicReduceOrder(SkPoint a[4]) { 25078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, 25178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com {a[2].fX, a[2].fY}, {a[3].fX, a[3].fY}}; 25278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com Cubic dst; 25347d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com int order = reduceOrder(aCubic, dst, kReduceOrder_QuadraticsAllowed, kReduceOrder_TreatAsFill); 25478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com for (int index = 0; index < order; ++index) { 25578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[index].fX = SkDoubleToScalar(dst[index].x); 25678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[index].fY = SkDoubleToScalar(dst[index].y); 25778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 25878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (order == 1) { // FIXME: allow returning points, caller should discard 25978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com a[1] = a[0]; 26078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return (SkPath::Verb) order; 26178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 26278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return (SkPath::Verb) (order - 1); 26378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com} 26478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 26578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comstatic bool IsCoincident(const SkPoint a[2], const SkPoint& above, 26678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const SkPoint& below) { 26778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}}; 26878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const _Line bLine = {{above.fX, above.fY}, {below.fX, below.fY}}; 26978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return implicit_matches_ulps(aLine, bLine, 32); 27078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com} 27178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 272c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com/* 273c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comlist of edges 274c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.combounds for edge 275c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comsort 276c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comactive T 277c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 278d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comif a contour's bounds is outside of the active area, no need to create edges 279c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com*/ 280c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 281d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com/* given one or more paths, 282c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com find the bounds of each contour, select the active contours 283c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for each active contour, compute a set of edges 284c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com each edge corresponds to one or more lines and curves 285c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com leave edges unbroken as long as possible 286c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com when breaking edges, compute the t at the break but leave the control points alone 287c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 288c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com */ 289c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 290c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid contourBounds(const SkPath& path, SkTDArray<SkRect>& boundsArray) { 291c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Iter iter(path, false); 292c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint pts[4]; 293c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb verb; 294c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkRect bounds; 295c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.setEmpty(); 296c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int count = 0; 297c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 298c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com switch (verb) { 299c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kMove_Verb: 300c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (!bounds.isEmpty()) { 301c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *boundsArray.append() = bounds; 302c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 303c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY); 304c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 0; 305c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 306d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case SkPath::kLine_Verb: 307c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 1; 308c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 309c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kQuad_Verb: 310c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 2; 311c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 312c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kCubic_Verb: 313c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 3; 314c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 315c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kClose_Verb: 316c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com count = 0; 317c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 318c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com default: 319c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkDEBUGFAIL("bad verb"); 320c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 321c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 322c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (int i = 1; i <= count; ++i) { 323c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bounds.growToInclude(pts[i].fX, pts[i].fY); 324c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 325c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 326c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 327c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 328f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic bool extendLine(const SkPoint line[2], const SkPoint& add) { 329f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // FIXME: allow this to extend lines that have slopes that are nearly equal 330f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dx1 = line[1].fX - line[0].fX; 331f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dy1 = line[1].fY - line[0].fY; 332f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dx2 = add.fX - line[0].fX; 333f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar dy2 = add.fY - line[0].fY; 334f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return dx1 * dy2 == dx2 * dy1; 335f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 3366680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 3372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZATION: this should point to a list of input data rather than duplicating 3382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// the line data here. This would reduce the need to assemble the results. 339f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstruct OutEdge { 340f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com bool operator<(const OutEdge& rh) const { 341cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& first = fPts[0]; 342cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& rhFirst = rh.fPts[0]; 343f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return first.fY == rhFirst.fY 344f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ? first.fX < rhFirst.fX 345f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com : first.fY < rhFirst.fY; 346f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 347752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 348cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkPoint fPts[4]; 3492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fID; // id of edge generating data 350cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com uint8_t fVerb; // FIXME: not read from everywhere 3512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fCloseCall; // edge is trimmable if not originally coincident 352f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com}; 353f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 3546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comclass OutEdgeBuilder { 3556680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.compublic: 356f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com OutEdgeBuilder(bool fill) 357f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com : fFill(fill) { 358f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 359f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 360a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com void addCurve(const SkPoint line[4], SkPath::Verb verb, int id, 361a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bool closeCall) { 362c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com OutEdge& newEdge = fEdges.push_back(); 363a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com memcpy(newEdge.fPts, line, (verb + 1) * sizeof(SkPoint)); 364a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com newEdge.fVerb = verb; 3652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com newEdge.fID = id; 3662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com newEdge.fCloseCall = closeCall; 3672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 368752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 3692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool trimLine(SkScalar y, int id) { 3702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t count = fEdges.count(); 3712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (count-- != 0) { 3722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com OutEdge& edge = fEdges[count]; 3732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fID != id) { 3742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 3752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fCloseCall) { 3772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 3782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(edge.fPts[0].fY <= y); 3802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edge.fPts[1].fY <= y) { 3812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 3822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge.fPts[1].fX = edge.fPts[0].fX + (y - edge.fPts[0].fY) 3842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com * (edge.fPts[1].fX - edge.fPts[0].fX) 3852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com / (edge.fPts[1].fY - edge.fPts[0].fY); 3862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edge.fPts[1].fY = y; 38778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#if DEBUG_TRIM_LINE 38878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkDebugf("%s edge=%d %1.9g,%1.9g\n", __FUNCTION__, id, 38978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com edge.fPts[1].fX, y); 39078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#endif 3912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return true; 3922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 3932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 394f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 395f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 396f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com void assemble(SkPath& simple) { 3976008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t listCount = fEdges.count(); 3986008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (listCount == 0) { 3996008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return; 4006008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 401f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 4026008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t listIndex = 0; 4036008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int advance = 1; 4046008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (listIndex < listCount && fTops[listIndex] == 0) { 4056008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++listIndex; 406f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 4076008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (listIndex >= listCount) { 4086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com break; 409f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 4104917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com int closeEdgeIndex = -listIndex - 1; 411fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // the curve is deferred and not added right away because the 412fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // following edge may extend the first curve. 413a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint firstPt, lastCurve[4]; 414a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com uint8_t lastVerb; 415fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 416fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int firstIndex, lastIndex; 417fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com const int tab = 8; 418fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 4196008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool doMove = true; 4206008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int edgeIndex; 4216008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com do { 422cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkPoint* ptArray = fEdges[listIndex].fPts; 423cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com uint8_t verb = fEdges[listIndex].fVerb; 424fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkPoint* curve[4]; 4256008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance < 0) { 426fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0] = &ptArray[verb]; 427fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kCubic_Verb) { 428fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[2]; 429fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[2] = &ptArray[1]; 430fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 431fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[verb] = &ptArray[0]; 4326008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 433fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0] = &ptArray[0]; 434fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kCubic_Verb) { 435fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[1]; 436fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[2] = &ptArray[2]; 437fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 438fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[verb] = &ptArray[verb]; 439fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 440fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (verb == SkPath::kQuad_Verb) { 441fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[1] = &ptArray[1]; 442f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 443a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (doMove) { 444fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstPt = *curve[0]; 445fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.moveTo(curve[0]->fX, curve[0]->fY); 446fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 447fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s %d moveTo (%g,%g)\n", __FUNCTION__, 448fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com listIndex + 1, curve[0]->fX, curve[0]->fY); 449fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstIndex = listIndex; 450fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 451fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = 0; index <= verb; ++index) { 452fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[index] = *curve[index]; 453a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 454a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com doMove = false; 455a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 456fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bool gap = lastCurve[lastVerb] != *curve[0]; 457fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (gap || lastVerb != SkPath::kLine_Verb) { // output the accumulated curve before the gap 458a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: see comment in bridge -- this probably 459a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // conceals errors 460fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fFill && UlpsDiff(lastCurve[lastVerb].fY, 461fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0]->fY) <= 10); 462a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (lastVerb) { 463a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 464a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.lineTo(lastCurve[1].fX, lastCurve[1].fY); 465a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 466a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 467a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.quadTo(lastCurve[1].fX, lastCurve[1].fY, 468a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[2].fX, lastCurve[2].fY); 469a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 470a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 471a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY, 472a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[2].fX, lastCurve[2].fY, 473a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com lastCurve[3].fX, lastCurve[3].fY); 474a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 475cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 476fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 477fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d %sTo (%g,%g)\n", tab, "", lastIndex + 1, 478fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kLVerbStr[lastVerb], lastCurve[lastVerb].fX, 479fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[lastVerb].fY); 480fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 481a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 482fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int firstCopy = 1; 48378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (gap || (lastVerb == SkPath::kLine_Verb 48478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com && (verb != SkPath::kLine_Verb 48578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com || !extendLine(lastCurve, *curve[verb])))) { 486a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: see comment in bridge -- this probably 487a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // conceals errors 488fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(lastCurve[lastVerb] == *curve[0] || 489fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com (fFill && UlpsDiff(lastCurve[lastVerb].fY, 490fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com curve[0]->fY) <= 10)); 491fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(curve[0]->fX, curve[0]->fY); 492fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 493fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d gap lineTo (%g,%g)\n", tab, "", 494fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex + 1, curve[0]->fX, curve[0]->fY); 495fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 496fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstCopy = 0; 497fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else if (lastVerb != SkPath::kLine_Verb) { 498fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstCopy = 0; 499a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 500fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (int index = firstCopy; index <= verb; ++index) { 501fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[index] = *curve[index]; 502a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 5036008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 504fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastVerb = verb; 505fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 506fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex = listIndex; 507fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 5086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance < 0) { 5096008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com edgeIndex = fTops[listIndex]; 5106008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[listIndex] = 0; 511fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 5126008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com edgeIndex = fBottoms[listIndex]; 5136008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[listIndex] = 0; 5146008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 5154917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex) { 5164917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com listIndex = abs(edgeIndex) - 1; 5174917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex < 0) { 5184917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fTops[listIndex] = 0; 5194917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } else { 5204917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fBottoms[listIndex] = 0; 5214917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 5224917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 5234917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (edgeIndex == closeEdgeIndex || edgeIndex == 0) { 524fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com switch (lastVerb) { 525fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kLine_Verb: 526fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(lastCurve[1].fX, lastCurve[1].fY); 527fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 528fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kQuad_Verb: 529fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.quadTo(lastCurve[1].fX, lastCurve[1].fY, 530fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[2].fX, lastCurve[2].fY); 531fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 532fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com case SkPath::kCubic_Verb: 533fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY, 534fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[2].fX, lastCurve[2].fY, 535fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[3].fX, lastCurve[3].fY); 536fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com break; 537fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 538fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 539fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d %sTo last (%g, %g)\n", tab, "", 540fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastIndex + 1, kLVerbStr[lastVerb], 541fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastCurve[lastVerb].fX, lastCurve[lastVerb].fY); 542fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 543a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (lastCurve[lastVerb] != firstPt) { 544fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com simple.lineTo(firstPt.fX, firstPt.fY); 545fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 546fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s %d final line (%g, %g)\n", tab, "", 547fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstIndex + 1, firstPt.fX, firstPt.fY); 548fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 5494917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 550cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com simple.close(); 551fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 552fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s close\n", tab, ""); 553fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 554cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com break; 555cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 556fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // if this and next edge go different directions 557fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_ASSEMBLE 558fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s advance=%d edgeIndex=%d flip=%s\n", tab, "", 559fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com advance, edgeIndex, advance > 0 ^ edgeIndex < 0 ? 560fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com "true" : "false"); 561fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 5626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (advance > 0 ^ edgeIndex < 0) { 5636008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com advance = -advance; 5646008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 5654917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } while (edgeIndex); 5666008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } while (true); 567f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 568752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 569cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // sort points by y, then x 570cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if x/y is identical, sort bottoms before tops 571cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if identical and both tops/bottoms, sort by angle 572cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com static bool lessThan(SkTArray<OutEdge>& edges, const int one, 573cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const int two) { 574cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const OutEdge& oneEdge = edges[abs(one) - 1]; 575cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com int oneIndex = one < 0 ? 0 : oneEdge.fVerb; 576cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& startPt1 = oneEdge.fPts[oneIndex]; 577cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const OutEdge& twoEdge = edges[abs(two) - 1]; 578cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com int twoIndex = two < 0 ? 0 : twoEdge.fVerb; 579cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& startPt2 = twoEdge.fPts[twoIndex]; 580cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (startPt1.fY != startPt2.fY) { 5812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d (%g,%g) %s startPt1.fY < startPt2.fY\n", __FUNCTION__, 5832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, startPt1.fY, startPt2.fY, 5842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com startPt1.fY < startPt2.fY ? "true" : "false"); 5852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 586cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return startPt1.fY < startPt2.fY; 587cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 588cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (startPt1.fX != startPt2.fX) { 5892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 5902e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d (%g,%g) %s startPt1.fX < startPt2.fX\n", __FUNCTION__, 5912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, startPt1.fX, startPt2.fX, 5922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com startPt1.fX < startPt2.fX ? "true" : "false"); 5932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 594cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return startPt1.fX < startPt2.fX; 595cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 596cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& endPt1 = oneEdge.fPts[oneIndex ^ oneEdge.fVerb]; 597cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& endPt2 = twoEdge.fPts[twoIndex ^ twoEdge.fVerb]; 598cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy1 = startPt1.fY - endPt1.fY; 599cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy2 = startPt2.fY - endPt2.fY; 600cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dy1y2 = dy1 * dy2; 601cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (dy1y2 < 0) { // different signs 6022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 603cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkDebugf("%s %d<%d %s dy1 > 0\n", __FUNCTION__, one, two, 604cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com dy1 > 0 ? "true" : "false"); 6052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 606cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return dy1 > 0; // one < two if one goes up and two goes down 607cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 608cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (dy1y2 == 0) { 6092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 6102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d %s endPt1.fX < endPt2.fX\n", __FUNCTION__, 6112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, endPt1.fX < endPt2.fX ? "true" : "false"); 6122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 613cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return endPt1.fX < endPt2.fX; 614d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 615cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dx1y2 = (startPt1.fX - endPt1.fX) * dy2; 616cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar dx2y1 = (startPt2.fX - endPt2.fX) * dy1; 6172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT_LESS_THAN 6182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s %d<%d %s dy2 < 0 ^ dx1y2 < dx2y1\n", __FUNCTION__, 6192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com one, two, dy2 < 0 ^ dx1y2 < dx2y1 ? "true" : "false"); 6202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 621cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return dy2 > 0 ^ dx1y2 < dx2y1; 622f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 623f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 6246008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // Sort the indices of paired points and then create more indices so 6256008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // assemble() can find the next edge and connect the top or bottom 626f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com void bridge() { 627f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t index; 628f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t count = fEdges.count(); 629f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com if (!count) { 630f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return; 631f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 632cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkASSERT(!fFill || count > 1); 633f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com fTops.setCount(count); 634f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com sk_bzero(fTops.begin(), sizeof(fTops[0]) * count); 635f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com fBottoms.setCount(count); 636f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com sk_bzero(fBottoms.begin(), sizeof(fBottoms[0]) * count); 6376008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> order; 6386008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 1; index <= count; ++index) { 6396008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com *order.append() = -index; 640f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 641cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com for (index = 1; index <= count; ++index) { 642cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com *order.append() = index; 643cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 644cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com QSort<SkTArray<OutEdge>, int>(fEdges, order.begin(), order.end() - 1, lessThan); 6456008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int* lastPtr = order.end() - 1; 6466008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int* leftPtr = order.begin(); 6476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (leftPtr < lastPtr) { 6486008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int leftIndex = *leftPtr; 6496008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int leftOutIndex = abs(leftIndex) - 1; 6506008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const OutEdge& left = fEdges[leftOutIndex]; 651f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int* rightPtr = leftPtr + 1; 6526008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int rightIndex = *rightPtr; 6536008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com int rightOutIndex = abs(rightIndex) - 1; 6546008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const OutEdge& right = fEdges[rightOutIndex]; 655cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool pairUp = fFill; 656cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (!pairUp) { 657cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& leftMatch = 658cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com left.fPts[leftIndex < 0 ? 0 : left.fVerb]; 659cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com const SkPoint& rightMatch = 660cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb]; 661cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com pairUp = leftMatch == rightMatch; 662cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } else { 6632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #if DEBUG_OUT 664d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // FIXME : not happy that error in low bit is allowed 665d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // this probably conceals error elsewhere 666d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY, 667d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) > 1) { 6682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *fMismatches.append() = leftIndex; 6692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (rightPtr == lastPtr) { 6702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *fMismatches.append() = rightIndex; 6712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 6722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com pairUp = false; 6732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 6742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #else 675d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkASSERT(UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY, 676d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) <= 10); 6772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com #endif 678cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 679cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (pairUp) { 6806008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (leftIndex < 0) { 6816008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[leftOutIndex] = rightIndex; 6826008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 6836008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[leftOutIndex] = rightIndex; 6846008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 6856008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (rightIndex < 0) { 6866008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fTops[rightOutIndex] = leftIndex; 6876008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } else { 6886008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fBottoms[rightOutIndex] = leftIndex; 689f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 6906008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++rightPtr; 691f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 692f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com leftPtr = rightPtr; 6936680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 6942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_OUT 6952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int* mismatch = fMismatches.begin(); 6962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (mismatch != fMismatches.end()) { 6972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int leftIndex = *mismatch++; 6982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int leftOutIndex = abs(leftIndex) - 1; 6992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const OutEdge& left = fEdges[leftOutIndex]; 7002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const SkPoint& leftPt = left.fPts[leftIndex < 0 ? 0 : left.fVerb]; 7012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s left=%d %s (%1.9g,%1.9g)\n", 7022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com __FUNCTION__, left.fID, leftIndex < 0 ? "top" : "bot", 7032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com leftPt.fX, leftPt.fY); 7042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 7052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(fMismatches.count() == 0); 7062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 707fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_BRIDGE 708fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < count; ++index) { 709fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com const OutEdge& edge = fEdges[index]; 710fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com uint8_t verb = edge.fVerb; 711d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com SkDebugf("%s %d edge=%d %s (%1.9g,%1.9g) (%1.9g,%1.9g)\n", 712fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com index == 0 ? __FUNCTION__ : " ", 713fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com index + 1, edge.fID, kLVerbStr[verb], edge.fPts[0].fX, 714fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge.fPts[0].fY, edge.fPts[verb].fX, edge.fPts[verb].fY); 715fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 716fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < count; ++index) { 717fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf(" top of % 2d connects to %s of % 2d\n", index + 1, 718fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fTops[index] < 0 ? "top " : "bottom", abs(fTops[index])); 719fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf(" bottom of % 2d connects to %s of % 2d\n", index + 1, 720fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fBottoms[index] < 0 ? "top " : "bottom", abs(fBottoms[index])); 721fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 722fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 7236680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 7246680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 7256008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.comprotected: 7266680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTArray<OutEdge> fEdges; 7276008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> fTops; 7286008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkTDArray<int> fBottoms; 729f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com bool fFill; 7302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_OUT 7312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<int> fMismatches; 7322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 7336680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com}; 7346680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 735c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com// Bounds, unlike Rect, does not consider a vertical line to be empty. 736c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comstruct Bounds : public SkRect { 737c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com static bool Intersects(const Bounds& a, const Bounds& b) { 738c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return a.fLeft <= b.fRight && b.fLeft <= a.fRight && 739c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com a.fTop <= b.fBottom && b.fTop <= a.fBottom; 740c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 741752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 7426008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool isEmpty() { 7436008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return fLeft > fRight || fTop > fBottom 7449f3e9a5a17a7546e1c5bfde1eb7e6e9c11870333caryclark@google.com || (fLeft == fRight && fTop == fBottom) 7456008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com || isnan(fLeft) || isnan(fRight) 7466008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com || isnan(fTop) || isnan(fBottom); 7476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 748c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 749c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 7504917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.comclass Intercepts { 7514917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.compublic: 7524917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com Intercepts() 7534917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com : fTopIntercepts(0) 754198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fBottomIntercepts(0) 755198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fExplicit(false) { 756198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 757d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 758198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com Intercepts& operator=(const Intercepts& src) { 759198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTs = src.fTs; 760198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTopIntercepts = src.fTopIntercepts; 761198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fBottomIntercepts = src.fBottomIntercepts; 762b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com return *this; 763198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 764198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 765198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: remove this function if it's never called 766198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double t(int tIndex) const { 767198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (tIndex == 0) { 768198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return 0; 769198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 770198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (tIndex > fTs.count()) { 771198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return 1; 772198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 773198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return fTs[tIndex - 1]; 7744917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 775752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 7762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 777a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com void dump(const SkPoint* pts, SkPath::Verb verb) { 7782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "Intercepts"; 7792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 8; 7802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (int i = 0; i < fTs.count(); ++i) { 7812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkPoint out; 782a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (verb) { 783a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 784a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(pts, fTs[i], &out); 785a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 786a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 787a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com QuadXYAtT(pts, fTs[i], &out); 788a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 789a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 790a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com CubicXYAtT(pts, fTs[i], &out); 791a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 792a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 793a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 794a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 795752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fTs[%d]=%1.9g (%1.9g,%1.9g)\n", tab + sizeof(className), 7962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fTs[i], out.fX, out.fY); 7972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 798198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fTopIntercepts=%u\n", tab + sizeof(className), 7992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fTopIntercepts); 800198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fBottomIntercepts=%u\n", tab + sizeof(className), 8012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fBottomIntercepts); 802fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s.fExplicit=%d\n", tab + sizeof(className), 803fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com className, fExplicit); 8042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 8052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 8062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 807c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<double> fTs; 808198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com unsigned char fTopIntercepts; // 0=init state 1=1 edge >1=multiple edges 809198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com unsigned char fBottomIntercepts; 810198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fExplicit; // if set, suppress 0 and 1 811d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 812c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 813c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 8142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstruct HorizontalEdge { 8152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool operator<(const HorizontalEdge& rh) const { 8162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fY == rh.fY ? fLeft == rh.fLeft ? fRight < rh.fRight 8172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com : fLeft < rh.fLeft : fY < rh.fY; 8182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 8192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 8202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 8212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void dump() { 8222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "HorizontalEdge"; 8232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 4; 824752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fLeft=%1.9g\n", tab + sizeof(className), className, fLeft); 825752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fRight=%1.9g\n", tab + sizeof(className), className, fRight); 826752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fY=%1.9g\n", tab + sizeof(className), className, fY); 8272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 8282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 8292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 8302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fLeft; 8312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fRight; 8322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar fY; 8332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com}; 8342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 8356680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstruct InEdge { 8366680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool operator<(const InEdge& rh) const { 837c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return fBounds.fTop == rh.fBounds.fTop 838c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ? fBounds.fLeft < rh.fBounds.fLeft 839c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com : fBounds.fTop < rh.fBounds.fTop; 840c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 841c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 8422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // Avoid collapsing t values that are close to the same since 8432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // we walk ts to describe consecutive intersections. Since a pair of ts can 8442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // be nearly equal, any problems caused by this should be taken care 845d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // of later. 8462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int add(double* ts, size_t count, ptrdiff_t verbIndex) { 847c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: in the pathological case where there is a ton of intercepts, binary search? 8486008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool foundIntercept = false; 8492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int insertedAt = -1; 8506008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com Intercepts& intercepts = fIntercepts[verbIndex]; 851c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < count; ++index) { 852c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com double t = ts[index]; 8534917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (t <= 0) { 854198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intercepts.fTopIntercepts <<= 1; 8554917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= ++intercepts.fTopIntercepts > 1; 8564917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com continue; 8574917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 8584917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (t >= 1) { 859198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com intercepts.fBottomIntercepts <<= 1; 8604917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= ++intercepts.fBottomIntercepts > 1; 8616008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com continue; 8626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 863198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntersected = true; 8646008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com foundIntercept = true; 865c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t tCount = intercepts.fTs.count(); 8662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double delta; 867c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t idx2 = 0; idx2 < tCount; ++idx2) { 868c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (t <= intercepts.fTs[idx2]) { 8692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: ? if (t < intercepts.fTs[idx2]) // failed 8702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com delta = intercepts.fTs[idx2] - t; 871cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (delta > 0) { 8722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com insertedAt = idx2; 873c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *intercepts.fTs.insert(idx2) = t; 874c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com goto nextPt; 876c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 877c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (tCount == 0 || (delta = t - intercepts.fTs[tCount - 1]) > 0) { 8792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com insertedAt = tCount; 880c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *intercepts.fTs.append() = t; 881c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPt: 8832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ; 884c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 8854917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fContainsIntercepts |= foundIntercept; 8862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return insertedAt; 887c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 888d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 889fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void addPartial(SkTArray<InEdge>& edges, int ptStart, int ptEnd, 890198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int verbStart, int verbEnd) { 891198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge* edge = edges.push_back_n(1); 892198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int verbCount = verbEnd - verbStart; 893198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts.push_back_n(verbCount); 894a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com // uint8_t* verbs = &fVerbs[verbStart]; 895198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int ceptIdx = 0; ceptIdx < verbCount; ++ceptIdx) { 896198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts[ceptIdx] = fIntercepts[verbStart + ceptIdx]; 897198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 898198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fPts.append(ptEnd - ptStart, &fPts[ptStart]); 899198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fVerbs.append(verbCount, &fVerbs[verbStart]); 900198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->setBounds(); 901198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fWinding = fWinding; 902198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know? 903198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 904198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 905fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void addSplit(SkTArray<InEdge>& edges, SkPoint* pts, uint8_t verb, 906fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts, int firstT, int lastT, bool flipped) { 907198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge* edge = edges.push_back_n(1); 908198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts.push_back_n(1); 909fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (firstT == 0) { 910fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = 0; 911fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 912fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = intercepts.fTs[firstT - 1]; 913fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 914fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com bool add1 = lastT == intercepts.fTs.count(); 915fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fIntercepts[0].fTs.append(lastT - firstT, &intercepts.fTs[firstT]); 916fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (add1) { 917fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edge->fIntercepts[0].fTs.append() = 1; 918fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 919198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fIntercepts[0].fExplicit = true; 920fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fPts.append(verb + 1, pts); 921198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fVerbs.append(1, &verb); 922fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // FIXME: bounds could be better for partial Ts 923fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->setSubBounds(); 924198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know? 925198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (flipped) { 926fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->flipTs(); 927fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fWinding = -fWinding; 928fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 929fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge->fWinding = fWinding; 930198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 931198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 932c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 9336680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool cached(const InEdge* edge) { 934c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: in the pathological case where there is a ton of edges, binary search? 935c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t count = fCached.count(); 936c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < count; ++index) { 937c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edge == fCached[index]) { 938c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return true; 939c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 940c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edge < fCached[index]) { 941c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCached.insert(index) = edge; 942c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 943c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 944c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 945c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCached.append() = edge; 946c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 947c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 948c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 949fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void complete(signed char winding) { 950198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com setBounds(); 951198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntercepts.push_back_n(fVerbs.count()); 952198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if ((fWinding = winding) < 0) { // reverse verbs, pts, if bottom to top 953198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com flip(); 954198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 955198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsIntercepts = fIntersected = false; 956198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 957d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 958fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void flip() { 959198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t index; 960198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t last = fPts.count() - 1; 961198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (index = 0; index < last; ++index, --last) { 962198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTSwap<SkPoint>(fPts[index], fPts[last]); 963198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 964198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com last = fVerbs.count() - 1; 965198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (index = 0; index < last; ++index, --last) { 966198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTSwap<uint8_t>(fVerbs[index], fVerbs[last]); 967198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 968198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 969d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 970fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void flipTs() { 971fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fIntercepts.count() == 1); 972fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts = fIntercepts[0]; 973fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(intercepts.fExplicit); 974fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTDArray<double>& ts = intercepts.fTs; 975fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com size_t index; 976fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com size_t last = ts.count() - 1; 977fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com for (index = 0; index < last; ++index, --last) { 978fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTSwap<double>(ts[index], ts[last]); 979fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 980fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 981198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 982198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com void reset() { 983198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fCached.reset(); 984198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntercepts.reset(); 985198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fPts.reset(); 986198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fVerbs.reset(); 987198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); 988198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fWinding = 0; 989198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fContainsIntercepts = false; 990198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fIntersected = false; 991198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 992198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 993198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com void setBounds() { 994c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint* ptPtr = fPts.begin(); 995c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint* ptLast = fPts.end(); 996c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (ptPtr == ptLast) { 997198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s empty edge\n", __FUNCTION__); 998c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkASSERT(0); 999c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: delete empty edge? 1000c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 1001c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1002c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fBounds.set(ptPtr->fX, ptPtr->fY, ptPtr->fX, ptPtr->fY); 1003c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ++ptPtr; 1004c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while (ptPtr != ptLast) { 1005c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fBounds.growToInclude(ptPtr->fX, ptPtr->fY); 1006c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com ++ptPtr; 1007c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1008198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1009d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1010fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com // recompute bounds based on subrange of T values 1011fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void setSubBounds() { 1012fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fIntercepts.count() == 1); 1013fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com Intercepts& intercepts = fIntercepts[0]; 1014fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(intercepts.fExplicit); 1015fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fVerbs.count() == 1); 1016fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkTDArray<double>& ts = intercepts.fTs; 1017fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (fVerbs[0] == SkPath::kQuad_Verb) { 1018fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fPts.count() == 3); 1019fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com QuadSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds); 1020fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } else { 1021fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fVerbs[0] == SkPath::kCubic_Verb); 1022fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkASSERT(fPts.count() == 4); 1023fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com CubicSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds); 1024fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 1025fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 1026198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 1027fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com void splitInflectionPts(SkTArray<InEdge>& edges) { 1028198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (!fIntersected) { 1029198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return; 1030198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1031198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t* verbs = fVerbs.begin(); 1032198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkPoint* pts = fPts.begin(); 1033198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastVerb = 0; 1034198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastPt = 0; 1035198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t verb; 1036198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool edgeSplit = false; 1037198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int ceptIdx = 0; ceptIdx < fIntercepts.count(); ++ceptIdx, pts += verb) { 1038198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com Intercepts& intercepts = fIntercepts[ceptIdx]; 1039198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com verb = *verbs++; 1040198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (verb <= SkPath::kLine_Verb) { 1041198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com continue; 1042198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1043198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com size_t tCount = intercepts.fTs.count(); 1044198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (!tCount) { 1045198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com continue; 1046198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1047a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com size_t tIndex = (size_t) -1; 1048198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar y = pts[0].fY; 1049198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int lastSplit = 0; 1050198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int firstSplit = -1; 1051198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool curveSplit = false; 1052198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com while (++tIndex < tCount) { 1053198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double nextT = intercepts.fTs[tIndex]; 1054198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkScalar nextY = verb == SkPath::kQuad_Verb 1055198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com ? QuadYAtT(pts, nextT) : CubicYAtT(pts, nextT); 1056198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (nextY < y) { 1057198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edgeSplit = curveSplit = true; 1058198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit < 0) { 1059198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = tIndex; 1060198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextPt = pts - fPts.begin(); 1061198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextVerb = verbs - 1 - fVerbs.begin(); 1062198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastVerb < nextVerb) { 1063fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addPartial(edges, lastPt, nextPt, lastVerb, nextVerb); 1064198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1065fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addPartial 1\n", __FUNCTION__); 1066198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1067198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1068198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastPt = nextPt; 1069198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastVerb = nextVerb; 1070198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1071198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } else { 1072198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit >= 0) { 1073198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastSplit < firstSplit) { 1074fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, 1075fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastSplit, firstSplit, false); 1076198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1077fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 1 tIndex=%d,%d\n", 1078fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com __FUNCTION__, lastSplit, firstSplit); 1079198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1080198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1081d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com addSplit(edges, pts, verb, intercepts, 1082fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, tIndex, true); 1083198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1084fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 2 tIndex=%d,%d flip\n", 1085fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com __FUNCTION__, firstSplit, tIndex); 1086198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1087198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com lastSplit = tIndex; 1088198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = -1; 1089198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1090198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1091198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com y = nextY; 1092198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1093198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (curveSplit) { 1094198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (firstSplit < 0) { 1095198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com firstSplit = lastSplit; 1096198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } else { 1097fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, lastSplit, 1098fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, false); 1099198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1100fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 3 tIndex=%d,%d\n", __FUNCTION__, 1101fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com lastSplit, firstSplit); 1102198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 1103198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1104fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addSplit(edges, pts, verb, intercepts, firstSplit, 1105fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com tIndex, pts[verb].fY < y); 1106198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1107fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addSplit 4 tIndex=%d,%d %s\n", __FUNCTION__, 1108fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com firstSplit, tIndex, pts[verb].fY < y ? "flip" : ""); 1109198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 11106680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1111198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1112198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // collapse remainder -- if there's nothing left, clear it somehow? 1113198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (edgeSplit) { 1114198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextVerb = verbs - 1 - fVerbs.begin(); 1115198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (lastVerb < nextVerb) { 1116198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int nextPt = pts - fPts.begin(); 1117fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com addPartial(edges, lastPt, nextPt, lastVerb, nextVerb); 1118198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #if DEBUG_SPLIT 1119fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s addPartial 2\n", __FUNCTION__); 1120198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com #endif 11216680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1122198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: reuse the edge instead of marking it empty 1123198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com reset(); 11246680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 11252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11262e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 11272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_DUMP 11282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void dump() { 11292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int i; 11302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const char className[] = "InEdge"; 11312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com const int tab = 4; 11322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("InEdge %p (edge=%d)\n", this, fID); 11332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fCached.count(); ++i) { 11342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fCached[%d]=0x%08x\n", tab + sizeof(className), 11352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fCached[i]); 11362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com uint8_t* verbs = fVerbs.begin(); 11382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkPoint* pts = fPts.begin(); 11392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fIntercepts.count(); ++i) { 11402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fIntercepts[%d]:\n", tab + sizeof(className), 11412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i); 1142a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fIntercepts[i].dump(pts, (SkPath::Verb) *verbs); 11432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com pts += *verbs++; 11442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fPts.count(); ++i) { 1146752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%*s.fPts[%d]=(%1.9g,%1.9g)\n", tab + sizeof(className), 11472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fPts[i].fX, fPts[i].fY); 11482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 11492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (i = 0; i < fVerbs.count(); ++i) { 11502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fVerbs[%d]=%d\n", tab + sizeof(className), 11512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, i, fVerbs[i]); 11522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1153fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s.fBounds=(%1.9g, %1.9g, %1.9g, %1.9g)\n", tab + sizeof(className), 11542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fBounds.fLeft, fBounds.fTop, 11552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fBounds.fRight, fBounds.fBottom); 11562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fWinding=%d\n", tab + sizeof(className), className, 11572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fWinding); 11582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className), 11592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com className, fContainsIntercepts); 1160198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%*s.fIntersected=%d\n", tab + sizeof(className), 1161198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com className, fIntersected); 1162c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 11632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 1164c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1165198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: temporary data : move this to a separate struct? 11666680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTDArray<const InEdge*> fCached; // list of edges already intercepted 1167c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTArray<Intercepts> fIntercepts; // one per verb 11684917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com 1169c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // persistent data 1170c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<SkPoint> fPts; 1171c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkTDArray<uint8_t> fVerbs; 1172c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com Bounds fBounds; 11732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fID; 1174c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com signed char fWinding; 11756680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com bool fContainsIntercepts; 1176198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fIntersected; 1177c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1178c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 11796680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comclass InEdgeBuilder { 1180c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.compublic: 1181c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 11822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comInEdgeBuilder(const SkPath& path, bool ignoreHorizontal, SkTArray<InEdge>& edges, 1183d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com SkTDArray<HorizontalEdge>& horizontalEdges) 1184c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com : fPath(path) 1185c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fCurrentEdge(NULL) 1186c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fEdges(edges) 11872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com , fHorizontalEdges(horizontalEdges) 1188c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com , fIgnoreHorizontal(ignoreHorizontal) 1189198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com , fContainsCurves(false) 1190c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com{ 1191c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com walk(); 1192c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1193c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1194198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.combool containsCurves() const { 1195198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return fContainsCurves; 1196198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 1197198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 1198c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comprotected: 1199c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1200c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid addEdge() { 1201f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 1202c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fCurrentEdge->fPts.append(fPtCount - fPtOffset, &fPts[fPtOffset]); 1203c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fPtOffset = 1; 1204c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *fCurrentEdge->fVerbs.append() = fVerb; 1205c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1206c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 12076008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.combool complete() { 12086008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (fCurrentEdge && fCurrentEdge->fVerbs.count()) { 1209fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com fCurrentEdge->complete(fWinding); 12106008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fCurrentEdge = NULL; 12116008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return true; 12126008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 12136008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return false; 12146008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com} 12156008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 121678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comint direction(SkPath::Verb verb) { 121778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com fPtCount = verb + 1; 12182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fIgnoreHorizontal && isHorizontal()) { 1219c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return 0; 1220c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 122178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return fPts[0].fY == fPts[verb].fY 122278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ? fPts[0].fX == fPts[verb].fX ? 0 : fPts[0].fX < fPts[verb].fX 122378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ? 1 : -1 : fPts[0].fY < fPts[verb].fY ? 1 : -1; 1224c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1225c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1226c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.combool isHorizontal() { 1227c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkScalar y = fPts[0].fY; 1228c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (int i = 1; i < fPtCount; ++i) { 1229c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (fPts[i].fY != y) { 1230c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return false; 1231c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1232c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1233c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return true; 1234c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1235c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1236c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid startEdge() { 12376008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (!fCurrentEdge) { 12386008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com fCurrentEdge = fEdges.push_back_n(1); 12396008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 1240c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fWinding = 0; 1241c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fPtOffset = 0; 1242c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1243c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1244c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comvoid walk() { 1245c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Iter iter(fPath, true); 12462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int winding = 0; 1247c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com while ((fVerb = iter.next(fPts)) != SkPath::kDone_Verb) { 1248c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com switch (fVerb) { 1249c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kMove_Verb: 1250c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com startEdge(); 1251c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1252c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kLine_Verb: 125378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding = direction(SkPath::kLine_Verb); 1254c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1255c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kQuad_Verb: 125678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com fVerb = QuadReduceOrder(fPts); 125778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding = direction(fVerb); 125878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com fContainsCurves |= fVerb == SkPath::kQuad_Verb; 1259c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1260c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kCubic_Verb: 126178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com fVerb = CubicReduceOrder(fPts); 126278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding = direction(fVerb); 126378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com fContainsCurves |= fVerb >= SkPath::kQuad_Verb; 1264c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com break; 1265c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com case SkPath::kClose_Verb: 1266f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 12676008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com complete(); 1268c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1269c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com default: 1270c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkDEBUGFAIL("bad verb"); 1271c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 1272c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 12732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (winding == 0) { 12742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge* horizontalEdge = fHorizontalEdges.append(); 12752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: for degenerate quads and cubics, compute x extremes 12762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fLeft = fPts[0].fX; 12772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fRight = fPts[fVerb].fX; 12782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horizontalEdge->fY = fPts[0].fY; 12792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (horizontalEdge->fLeft > horizontalEdge->fRight) { 12802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTSwap<SkScalar>(horizontalEdge->fLeft, horizontalEdge->fRight); 12812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 12826008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (complete()) { 12836008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com startEdge(); 12846008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 1285c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com continue; 1286c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1287c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (fWinding + winding == 0) { 1288c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // FIXME: if prior verb or this verb is a horizontal line, reverse 1289c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // it instead of starting a new edge 1290f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkASSERT(fCurrentEdge); 1291cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (complete()) { 1292cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com startEdge(); 1293cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1294c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1295c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com fWinding = winding; 1296c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com addEdge(); 1297c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 12986b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (!complete()) { 12996b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (fCurrentEdge) { 13006b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com fEdges.pop_back(); 13016b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 13026b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 1303c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 1304c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1305c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.comprivate: 1306c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const SkPath& fPath; 13076680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com InEdge* fCurrentEdge; 13086680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkTArray<InEdge>& fEdges; 13092e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge>& fHorizontalEdges; 1310c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPoint fPts[4]; 1311c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb fVerb; 1312c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int fPtCount; 1313c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int fPtOffset; 1314c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com int8_t fWinding; 1315c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com bool fIgnoreHorizontal; 1316198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fContainsCurves; 1317c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1318c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13196680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstruct WorkEdge { 1320c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkScalar bottom() const { 13216680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fPts[verb()].fY; 1322c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1323c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13246680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void init(const InEdge* edge) { 13256680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fEdge = edge; 13266680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fPts = edge->fPts.begin(); 13276680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fVerb = edge->fVerbs.begin(); 1328c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1329c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1330cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool advance() { 13316680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com SkASSERT(fVerb < fEdge->fVerbs.end()); 13326680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fPts += *fVerb++; 13336680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fVerb != fEdge->fVerbs.end(); 1334c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1335d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 133678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const SkPoint* lastPoints() const { 133778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(fPts >= fEdge->fPts.begin() + lastVerb()); 133878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return &fPts[-lastVerb()]; 133978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1340752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1341cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPath::Verb lastVerb() const { 1342cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkASSERT(fVerb > fEdge->fVerbs.begin()); 1343cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return (SkPath::Verb) fVerb[-1]; 1344cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1345cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com 134678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const SkPoint* points() const { 134778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return fPts; 134878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1349c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1350c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com SkPath::Verb verb() const { 1351c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return (SkPath::Verb) *fVerb; 1352c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1353c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13546008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ptrdiff_t verbIndex() const { 13556680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fVerb - fEdge->fVerbs.begin(); 13566680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1357752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 13586680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com int winding() const { 13596680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return fEdge->fWinding; 1360c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1361c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13626680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com const InEdge* fEdge; 1363c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const SkPoint* fPts; 1364c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com const uint8_t* fVerb; 1365c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1366c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 13676680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// always constructed with SkTDArray because new edges are inserted 13686680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// this may be a inappropriate optimization, suggesting that a separate array of 13696680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com// ActiveEdge* may be faster to insert and search 1370cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com 1371cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com// OPTIMIZATION: Brian suggests that global sorting should be unnecessary, since 1372cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com// as active edges are introduced, only local sorting should be required 13732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comclass ActiveEdge { 13742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.compublic: 137578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // this logic must be kept in sync with tooCloseToCall 1376fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // callers expect this to only read fAbove, fTangent 13776008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bool operator<(const ActiveEdge& rh) const { 1378fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb == rh.fVerb) { 1379fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // FIXME: don't know what to do if verb is quad, cubic 1380fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com return abCompare(fAbove, fBelow, rh.fAbove, rh.fBelow); 1381fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1382fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // figure out which is quad, line 1383fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // if cached data says line did not intersect quad, use top/bottom 1384fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb != SkPath::kLine_Verb ? noIntersect(rh) : rh.noIntersect(*this)) { 1385fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com return abCompare(fAbove, fBelow, rh.fAbove, rh.fBelow); 1386fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1387d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // use whichever of top/tangent tangent/bottom overlaps more 1388fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // with line top/bot 1389fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // assumes quad/cubic can already be upconverted to cubic/cubic 1390fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com const SkPoint* line[2]; 1391fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com const SkPoint* curve[4]; 1392fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb != SkPath::kLine_Verb) { 1393fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com line[0] = &rh.fAbove; 1394fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com line[1] = &rh.fBelow; 1395fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[0] = &fAbove; 1396fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[1] = &fTangent; 1397fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[2] = &fBelow; 1398fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else { 1399fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com line[0] = &fAbove; 1400fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com line[1] = &fBelow; 1401fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[0] = &rh.fAbove; 1402fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[1] = &rh.fTangent; 1403fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com curve[2] = &rh.fBelow; 1404fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1405b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com // FIXME: code has been abandoned, incomplete.... 1406b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com return false; 1407fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1408d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1409fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com bool abCompare(const SkPoint& a1, const SkPoint& a2, const SkPoint& b1, 1410fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com const SkPoint& b2) const { 1411fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com double topD = a1.fX - b1.fX; 1412fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (b1.fY < a1.fY) { 1413fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com topD = (b2.fY - b1.fY) * topD - (a1.fY - b1.fY) * (b2.fX - b1.fX); 1414fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else if (b1.fY > a1.fY) { 1415fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com topD = (a2.fY - a1.fY) * topD + (b1.fY - a1.fY) * (a2.fX - a1.fX); 1416fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1417fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com double botD = a2.fX - b2.fX; 1418fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (b2.fY > a2.fY) { 1419fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com botD = (b2.fY - b1.fY) * botD - (a2.fY - b2.fY) * (b2.fX - b1.fX); 1420fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else if (b2.fY < a2.fY) { 1421fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com botD = (a2.fY - a1.fY) * botD + (b2.fY - a2.fY) * (a2.fX - a1.fX); 1422d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1423d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com // return sign of greater absolute value 1424d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com return (fabs(topD) > fabs(botD) ? topD : botD) < 0; 1425d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1426d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com 14272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // If a pair of edges are nearly coincident for some span, add a T in the 14282e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // edge so it can be shortened to match the other edge. Note that another 14292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // approach is to trim the edge after it is added to the OutBuilder list -- 14302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: since this has no effect if the edge is already done (i.e., 14312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fYBottom >= y) maybe this can only be done by calling trimLine later. 14322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYBelow(SkScalar y) { 14332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fBelow.fY <= y || fYBottom >= y) { 14342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 14352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addTatYInner(y); 14372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fFixBelow = true; 14382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1439752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 14402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYAbove(SkScalar y) { 14412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fBelow.fY <= y) { 14422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 14432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addTatYInner(y); 14452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 14472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void addTatYInner(SkScalar y) { 1448752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (fWorkEdge.fPts[0].fY > y) { 1449752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com backup(y); 1450752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 14512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar left = fWorkEdge.fPts[0].fX; 14522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar right = fWorkEdge.fPts[1].fX; 14532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (left > right) { 14542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTSwap(left, right); 14552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1456752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com double ts[2]; 145778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(fWorkEdge.fVerb[0] == SkPath::kLine_Verb); 14582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int pts = LineIntersect(fWorkEdge.fPts, left, right, y, ts); 14592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(pts == 1); 14602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // An ActiveEdge or WorkEdge has no need to modify the T values computed 14612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // in the InEdge, except in the following case. If a pair of edges are 14622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // nearly coincident, this may not be detected when the edges are 14632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // intersected. Later, when sorted, and this near-coincidence is found, 14642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // an additional t value must be added, requiring the cast below. 14652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* writable = const_cast<InEdge*>(fWorkEdge.fEdge); 14662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int insertedAt = writable->add(ts, pts, fWorkEdge.verbIndex()); 1467752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 1468752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d y=%1.9g t=%1.9g\n", __FUNCTION__, ID(), y, ts[0]); 1469752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 14702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (insertedAt >= 0) { 14712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (insertedAt + 1 < fTIndex) { 14722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkASSERT(insertedAt + 2 == fTIndex); 14732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com --fTIndex; 14742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 14776008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 1478cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool advanceT() { 1479198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(fTIndex <= fTs->count() - fExplicitTs); 1480198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return ++fTIndex <= fTs->count() - fExplicitTs; 1481cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 14822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 1483cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool advance() { 1484cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // FIXME: flip sense of next 1485cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool result = fWorkEdge.advance(); 1486cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com fDone = !result; 1487cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com initT(); 1488cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return result; 1489cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1490752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1491752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com void backup(SkScalar y) { 1492752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com do { 1493752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkASSERT(fWorkEdge.fEdge->fVerbs.begin() < fWorkEdge.fVerb); 1494752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com fWorkEdge.fPts -= *--fWorkEdge.fVerb; 1495752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkASSERT(fWorkEdge.fEdge->fPts.begin() <= fWorkEdge.fPts); 1496752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } while (fWorkEdge.fPts[0].fY >= y); 1497752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com initT(); 1498198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(!fExplicitTs); 1499752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com fTIndex = fTs->count() + 1; 1500752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 1501d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1502fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com void calcAboveBelow(double tAbove, double tBelow) { 1503fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fVerb = fWorkEdge.verb(); 1504fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com switch (fVerb) { 1505fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com case SkPath::kLine_Verb: 1506fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com LineXYAtT(fWorkEdge.fPts, tAbove, &fAbove); 1507fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com LineXYAtT(fWorkEdge.fPts, tBelow, &fTangent); 1508fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fBelow = fTangent; 1509fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com break; 1510fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com case SkPath::kQuad_Verb: 1511fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // FIXME: put array in struct to avoid copy? 1512fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkPoint quad[3]; 1513fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com QuadSubDivide(fWorkEdge.fPts, tAbove, tBelow, quad); 1514fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fAbove = quad[0]; 1515fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fTangent = quad[0] != quad[1] ? quad[1] : quad[2]; 1516fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fBelow = quad[2]; 1517fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com break; 1518fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com case SkPath::kCubic_Verb: 1519fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkPoint cubic[3]; 1520fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com CubicSubDivide(fWorkEdge.fPts, tAbove, tBelow, cubic); 1521fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fAbove = cubic[0]; 1522fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // FIXME: can't see how quad logic for how tangent is used 1523d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // extends to cubic 1524fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fTangent = cubic[0] != cubic[1] ? cubic[1] 1525fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com : cubic[0] != cubic[2] ? cubic[2] : cubic[3]; 1526fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fBelow = cubic[3]; 1527fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com break; 1528fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com default: 1529fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkASSERT(0); 1530fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1531fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1532752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1533cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com void calcLeft(SkScalar y) { 1534cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // OPTIMIZE: put a kDone_Verb at the end of the verb list? 15354917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (fDone || fBelow.fY > y) { 1536cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return; // nothing to do; use last 15374917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 1538cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com calcLeft(); 1539752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (fAbove.fY == fBelow.fY) { 1540752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d fAbove.fY != fBelow.fY %1.9g\n", __FUNCTION__, 1541752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com ID(), fAbove.fY); 1542752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 1543cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1544752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1545cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com void calcLeft() { 1546198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int add = (fTIndex <= fTs->count() - fExplicitTs) - 1; 1547a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double tAbove = t(fTIndex + add); 1548a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com double tBelow = t(fTIndex - ~add); 1549fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // OPTIMIZATION: if fAbove, fBelow have already been computed 1550fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // for the fTIndex, don't do it again 1551fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com calcAboveBelow(tAbove, tBelow); 1552fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // For identical x, this lets us know which edge is first. 1553fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // If both edges have T values < 1, check x at next T (fBelow). 1554a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(tAbove != tBelow); 1555a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: this can loop forever 1556a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // need a break if we hit the end 1557198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: in unit test, figure out how explicit Ts work as well 1558a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com while (fAbove.fY == fBelow.fY) { 1559a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (add < 0 || fTIndex == fTs->count()) { 1560a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com add -= 1; 1561a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(fTIndex + add >= 0); 1562a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com tAbove = t(fTIndex + add); 1563a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 1564a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com add += 1; 1565a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(fTIndex - ~add <= fTs->count() + 1); 1566a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com tBelow = t(fTIndex - ~add); 1567a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1568fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com calcAboveBelow(tAbove, tBelow); 1569a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1570a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fTAbove = tAbove; 1571a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com fTBelow = tBelow; 15726008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 15736008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 1574752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com bool done(SkScalar bottom) const { 1575752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com return fDone || fYBottom >= bottom; 1576cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1577d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 15782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com void fixBelow() { 15792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (fFixBelow) { 1580fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fTBelow = nextT(); 1581fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com calcAboveBelow(fTAbove, fTBelow); 15822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com fFixBelow = false; 15832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 15842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 15852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 15866680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void init(const InEdge* edge) { 15876680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fWorkEdge.init(edge); 1588fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fDone = false; 15896680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com initT(); 15904917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com fBelow.fY = SK_ScalarMin; 1591cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com fYBottom = SK_ScalarMin; 15926680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1593752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 15946680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com void initT() { 15956008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const Intercepts& intercepts = fWorkEdge.fEdge->fIntercepts.front(); 15966008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkASSERT(fWorkEdge.verbIndex() <= fWorkEdge.fEdge->fIntercepts.count()); 15976008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com const Intercepts* interceptPtr = &intercepts + fWorkEdge.verbIndex(); 1598198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fTs = &interceptPtr->fTs; 1599198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com fExplicitTs = interceptPtr->fExplicit; 16006008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // the above is conceptually the same as 16016008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // fTs = &fWorkEdge.fEdge->fIntercepts[fWorkEdge.verbIndex()].fTs; 16026008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com // but templated arrays don't allow returning a pointer to the end() element 16036680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com fTIndex = 0; 1604fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (!fDone) { 1605fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com fVerb = fWorkEdge.verb(); 1606fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 1607fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkASSERT(fVerb > SkPath::kMove_Verb); 16086680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 1609752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1610cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // OPTIMIZATION: record if two edges are coincident when the are intersected 1611cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // It's unclear how to do this -- seems more complicated than recording the 1612cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // t values, since the same t values could exist intersecting non-coincident 1613cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com // edges. 161478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com bool isCoincidentWith(const ActiveEdge* edge) const { 1615d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (fAbove != edge->fAbove || fBelow != edge->fBelow) { 1616d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com return false; 1617d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1618fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb != edge->fVerb) { 1619cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1620cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1621fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com switch (fVerb) { 162278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com case SkPath::kLine_Verb: 16234917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com return true; 1624cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com default: 162578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // FIXME: add support for quads, cubics 1626cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkASSERT(0); 162778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return false; 1628cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1629cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return false; 1630cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1631752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 163278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com bool isUnordered(const ActiveEdge* edge) const { 163378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return fAbove == edge->fAbove && fBelow == edge->fBelow; 163478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 163578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 1636fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com// SkPath::Verb lastVerb() const { 1637fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com// return fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb(); 1638fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com// } 1639d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 164078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const SkPoint* lastPoints() const { 164178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return fDone ? fWorkEdge.lastPoints() : fWorkEdge.points(); 164278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1643d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1644fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com bool noIntersect(const ActiveEdge& ) const { 1645fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // incomplete 1646fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com return false; 1647fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } 164878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 16492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // The shortest close call edge should be moved into a position where 16502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // it contributes if the winding is transitioning to or from zero. 16512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool swapClose(const ActiveEdge* next, int prev, int wind, int mask) const { 1652d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#if DEBUG_ADJUST_COINCIDENT 1653d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkDebugf("%s edge=%d (%g) next=%d (%g) prev=%d wind=%d nextWind=%d\n", 1654d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com __FUNCTION__, ID(), fBelow.fY, next->ID(), next->fBelow.fY, 1655d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com prev, wind, wind + next->fWorkEdge.winding()); 1656d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#endif 16572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((prev & mask) == 0 || (wind & mask) == 0) { 16582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return next->fBelow.fY < fBelow.fY; 16592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 16602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int nextWinding = wind + next->fWorkEdge.winding(); 16612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((nextWinding & mask) == 0) { 16622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fBelow.fY < next->fBelow.fY; 16632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 16642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return false; 16652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1666752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 1667cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com bool swapCoincident(const ActiveEdge* edge, SkScalar bottom) const { 1668cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (fBelow.fY >= bottom || fDone || edge->fDone) { 1669cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1670cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1671cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com ActiveEdge thisWork = *this; 1672cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com ActiveEdge edgeWork = *edge; 1673cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com while ((thisWork.advanceT() || thisWork.advance()) 1674cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com && (edgeWork.advanceT() || edgeWork.advance())) { 1675cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com thisWork.calcLeft(); 1676cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com edgeWork.calcLeft(); 1677cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (thisWork < edgeWork) { 1678cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1679cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1680cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com if (edgeWork < thisWork) { 1681cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return true; 1682cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1683cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 1684cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com return false; 1685cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1686d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1687a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com bool swapUnordered(const ActiveEdge* edge, SkScalar /* bottom */) const { 1688fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkASSERT(fVerb != SkPath::kLine_Verb 1689fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com || edge->fVerb != SkPath::kLine_Verb); 169078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (fDone || edge->fDone) { 169178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return false; 169278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 169378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ActiveEdge thisWork, edgeWork; 169478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com extractAboveBelow(thisWork); 169578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com edge->extractAboveBelow(edgeWork); 169678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return edgeWork < thisWork; 169778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1698752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 16992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool tooCloseToCall(const ActiveEdge* edge) const { 17002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int ulps; 1701d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com double t1, t2, b1, b2; 170278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // This logic must be kept in sync with operator < 1703d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (edge->fAbove.fY < fAbove.fY) { 1704fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com t1 = (edge->fTangent.fY - edge->fAbove.fY) * (fAbove.fX - edge->fAbove.fX); 1705fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com t2 = (fAbove.fY - edge->fAbove.fY) * (edge->fTangent.fX - edge->fAbove.fX); 1706d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else if (edge->fAbove.fY > fAbove.fY) { 1707fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com t1 = (fTangent.fY - fAbove.fY) * (fAbove.fX - edge->fAbove.fX); 1708fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com t2 = (fAbove.fY - edge->fAbove.fY) * (fTangent.fX - fAbove.fX); 1709d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1710d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t1 = fAbove.fX; 1711d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com t2 = edge->fAbove.fX; 1712d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1713fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (edge->fTangent.fY > fTangent.fY) { 1714fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b1 = (edge->fTangent.fY - edge->fAbove.fY) * (fTangent.fX - edge->fTangent.fX); 1715fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b2 = (fTangent.fY - edge->fTangent.fY) * (edge->fTangent.fX - edge->fAbove.fX); 1716fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else if (edge->fTangent.fY < fTangent.fY) { 1717fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b1 = (fTangent.fY - fAbove.fY) * (fTangent.fX - edge->fTangent.fX); 1718fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b2 = (fTangent.fY - edge->fTangent.fY) * (fTangent.fX - fAbove.fX); 1719d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1720fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b1 = fTangent.fX; 1721fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com b2 = edge->fTangent.fX; 1722d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1723d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com if (fabs(t1 - t2) > fabs(b1 - b2)) { 1724b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com ulps = UlpsDiff((float) t1, (float) t2); 1725d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } else { 1726b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com ulps = UlpsDiff((float) b1, (float) b2); 1727d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com } 1728d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#if DEBUG_ADJUST_COINCIDENT 1729d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com SkDebugf("%s this=%d edge=%d ulps=%d\n", __FUNCTION__, ID(), edge->ID(), 1730d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com ulps); 1731d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com#endif 173278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (ulps < 0 || ulps > 32) { 173378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return false; 173478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1735fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb == SkPath::kLine_Verb && edge->fVerb == SkPath::kLine_Verb) { 173678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return true; 173778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 1738fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb != SkPath::kLine_Verb && edge->fVerb != SkPath::kLine_Verb) { 173978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return false; 174078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 174178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 174278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com double ts[2]; 174378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com bool isLine = true; 174478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com bool curveQuad = true; 1745fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (fVerb == SkPath::kCubic_Verb) { 174678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[0] = (fTAbove * 2 + fTBelow) / 3; 174778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[1] = (fTAbove + fTBelow * 2) / 3; 174878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com curveQuad = isLine = false; 1749fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else if (edge->fVerb == SkPath::kCubic_Verb) { 175078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[0] = (edge->fTAbove * 2 + edge->fTBelow) / 3; 175178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[1] = (edge->fTAbove + edge->fTBelow * 2) / 3; 175278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com curveQuad = false; 1753fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com } else if (fVerb == SkPath::kQuad_Verb) { 175478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[0] = fTAbove; 175578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[1] = (fTAbove + fTBelow) / 2; 175678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com isLine = false; 175778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } else { 1758fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkASSERT(edge->fVerb == SkPath::kQuad_Verb); 175978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[0] = edge->fTAbove; 176078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ts[1] = (edge->fTAbove + edge->fTBelow) / 2; 176178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 176278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const SkPoint* curvePts = isLine ? edge->lastPoints() : lastPoints(); 176378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com const ActiveEdge* lineEdge = isLine ? this : edge; 176478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkPoint curveSample[2]; 176578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com for (int index = 0; index < 2; ++index) { 176678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (curveQuad) { 176778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com QuadXYAtT(curvePts, ts[index], &curveSample[index]); 176878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } else { 176978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com CubicXYAtT(curvePts, ts[index], &curveSample[index]); 177078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 177178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 177278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return IsCoincident(curveSample, lineEdge->fAbove, lineEdge->fBelow); 17732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1774d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 17752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double nextT() const { 1776198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(fTIndex <= fTs->count() - fExplicitTs); 1777cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return t(fTIndex + 1); 1778cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1779c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1780cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double t() const { 1781198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return t(fTIndex); 1782c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 1783c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 1784cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double t(int tIndex) const { 1785198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (fExplicitTs) { 1786198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(tIndex < fTs->count()); 1787198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com return (*fTs)[tIndex]; 1788d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 1789cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (tIndex == 0) { 1790cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return 0; 1791cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1792cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (tIndex > fTs->count()) { 1793cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return 1; 1794cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1795cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com return (*fTs)[tIndex - 1]; 1796cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1797cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com 17982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: debugging only 1799752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com int ID() const { 18002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return fWorkEdge.fEdge->fID; 18012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 18022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 180378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comprivate: 180478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // utility used only by swapUnordered 180578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com void extractAboveBelow(ActiveEdge& extracted) const { 180678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkPoint curve[4]; 1807fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com switch (fVerb) { 1808d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case SkPath::kLine_Verb: 180978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com extracted.fAbove = fAbove; 1810fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com extracted.fTangent = fTangent; 181178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com return; 181278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com case SkPath::kQuad_Verb: 181378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com QuadSubDivide(lastPoints(), fTAbove, fTBelow, curve); 181478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com break; 181578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com case SkPath::kCubic_Verb: 181678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com CubicSubDivide(lastPoints(), fTAbove, fTBelow, curve); 181778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com break; 181878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com default: 181978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(0); 182078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 182178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com extracted.fAbove = curve[0]; 1822fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com extracted.fTangent = curve[1]; 182378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 182478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com 18252e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.compublic: 18266680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com WorkEdge fWorkEdge; 18276680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com const SkTDArray<double>* fTs; 1828cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPoint fAbove; 1829fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkPoint fTangent; 1830cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkPoint fBelow; 183178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com double fTAbove; // OPTIMIZATION: only required if edge has quads or cubics 18322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com double fTBelow; 1833cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com SkScalar fYBottom; 18342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int fCoincident; 18356680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com int fTIndex; 1836fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkPath::Verb fVerb; 18372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fSkip; // OPTIMIZATION: use bitfields? 18382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fCloseCall; 1839cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool fDone; 18402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool fFixBelow; 1841198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com bool fExplicitTs; 1842c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com}; 1843c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com 18446680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.comstatic void addToActive(SkTDArray<ActiveEdge>& activeEdges, const InEdge* edge) { 18456680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com size_t count = activeEdges.count(); 18466680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com for (size_t index = 0; index < count; ++index) { 18476680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com if (edge == activeEdges[index].fWorkEdge.fEdge) { 18486680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com return; 18496680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 18506680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 18516680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com ActiveEdge* active = activeEdges.append(); 18526680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com active->init(edge); 18536680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com} 18546680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 18554917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// Find any intersections in the range of active edges. A pair of edges, on 18564917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// either side of another edge, may change the winding contribution for part of 1857d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com// the edge. 18582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// Keep horizontal edges just for 18594917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com// the purpose of computing when edges change their winding contribution, since 1860d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com// this is essentially computing the horizontal intersection. 18612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic void addBottomT(InEdge** currentPtr, InEdge** lastPtr, 18622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** horizontal) { 18632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** testPtr = currentPtr - 1; 18642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge* horzEdge = *horizontal; 18652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar left = horzEdge->fLeft; 18662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar bottom = horzEdge->fY; 18672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (++testPtr != lastPtr) { 18682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* test = *testPtr; 18692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (test->fBounds.fBottom <= bottom || test->fBounds.fRight <= left) { 18702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com continue; 18712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 18722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com WorkEdge wt; 18732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com wt.init(test); 18742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 18752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** sorted = horizontal; 18762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horzEdge = *sorted; 1877f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 1878198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com double wtTs[4]; 1879198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com int pts; 1880198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com uint8_t verb = wt.verb(); 1881198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com switch (verb) { 1882198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kLine_Verb: 1883198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = LineIntersect(wt.fPts, horzEdge->fLeft, 1884198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1885198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1886198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kQuad_Verb: 1887198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = QuadIntersect(wt.fPts, horzEdge->fLeft, 1888198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1889198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1890198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com case SkPath::kCubic_Verb: 1891198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com pts = CubicIntersect(wt.fPts, horzEdge->fLeft, 1892198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fRight, horzEdge->fY, wtTs); 1893198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com break; 1894198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1895198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (pts) { 18962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ADD_BOTTOM_TS 1897198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int x = 0; x < pts; ++x) { 1898198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s y=%g wtTs[0]=%g (%g,%g", __FUNCTION__, 1899198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com horzEdge->fY, wtTs[x], wt.fPts[0].fX, wt.fPts[0].fY); 1900198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int y = 0; y < verb; ++y) { 1901198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf(" %g,%g", wt.fPts[y + 1].fX, wt.fPts[y + 1].fY)); 19022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1903198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf(")\n"); 1904f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1905198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (pts > verb) { 1906198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkASSERT(0); // FIXME ? should this work? 1907198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]); 1908198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 1909198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 1910198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com test->add(wtTs, pts, wt.verbIndex()); 1911f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 19122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com horzEdge = *++sorted; 19132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (horzEdge->fY == bottom 19142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com && horzEdge->fLeft <= test->fBounds.fRight); 19152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (wt.advance()); 1916f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 1917f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 1918f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 1919a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#if DEBUG_ADD_INTERSECTING_TS 1920a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.comstatic void debugShowLineIntersection(int pts, const WorkEdge& wt, 1921a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com const WorkEdge& wn, const double wtTs[2], const double wnTs[2]) { 1922a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (!pts) { 1923a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com return; 1924a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1925a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint wtOutPt, wnOutPt; 1926a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(wt.fPts, wtTs[0], &wtOutPt); 1927a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineXYAtT(wn.fPts, wnTs[0], &wnOutPt); 1928fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s wtTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n", 1929a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com __FUNCTION__, 1930a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com wtTs[0], wt.fPts[0].fX, wt.fPts[0].fY, 1931fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com wt.fPts[1].fX, wt.fPts[1].fY, wtOutPt.fX, wtOutPt.fY); 1932a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (pts == 2) { 1933a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]); 1934a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1935fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%s wnTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n", 1936a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com __FUNCTION__, 1937a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com wnTs[0], wn.fPts[0].fX, wn.fPts[0].fY, 1938fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com wn.fPts[1].fX, wn.fPts[1].fY, wnOutPt.fX, wnOutPt.fY); 1939a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (pts == 2) { 1940a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkDebugf("%s wnTs[1]=%g\n", __FUNCTION__, wnTs[1]); 1941a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1942a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com} 1943a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#else 1944a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.comstatic void debugShowLineIntersection(int , const WorkEdge& , 1945a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com const WorkEdge& , const double [2], const double [2]) { 1946a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com} 1947a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#endif 1948a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com 1949f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) { 1950cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge** testPtr = currentPtr - 1; 1951752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // FIXME: lastPtr should be past the point of interest, so 1952752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // test below should be lastPtr - 2 1953752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com // that breaks testSimplifyTriangle22, so further investigation is needed 1954cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com while (++testPtr != lastPtr - 1) { 1955cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge* test = *testPtr; 1956cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge** nextPtr = testPtr; 1957cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com do { 1958cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com InEdge* next = *++nextPtr; 1959198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // FIXME: this compares against the sentinel sometimes 1960198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // OPTIMIZATION: this may never be needed since this gets called 1961198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // in two passes now. Verify that double hits are appropriate. 1962cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (test->cached(next)) { 1963cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com continue; 1964cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1965cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com if (!Bounds::Intersects(test->fBounds, next->fBounds)) { 1966cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com continue; 1967cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 1968f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com WorkEdge wt, wn; 1969f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wt.init(test); 1970f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wn.init(next); 1971f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 1972a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com int pts; 1973a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com Intersections ts; 1974a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bool swap = false; 1975a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wt.verb()) { 1976a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 1977a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 1978a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 1979a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = LineIntersect(wt.fPts, wn.fPts, ts); 1980a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com debugShowLineIntersection(pts, wt, wn, 1981a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com ts.fT[0], ts.fT[1]); 1982a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1983a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1984a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 1985a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com swap = true; 1986a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadLineIntersect(wn.fPts, wt.fPts, ts); 1987a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1988a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1989a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 1990a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com swap = true; 1991a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicLineIntersect(wn.fPts, wt.fPts, ts); 1992a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1993a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 1994a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 1995a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 19962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 1997a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 1998a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 1999a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 2000a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 2001a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadLineIntersect(wt.fPts, wn.fPts, ts); 2002a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2003a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2004a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 2005a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = QuadIntersect(wt.fPts, wn.fPts, ts); 2006a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2007a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2008a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 2009a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: promote quad to cubic 2010a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 2011a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2012a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2013a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2014a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 20152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 2016a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2017a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 2018a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wn.verb()) { 2019a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 2020a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicLineIntersect(wt.fPts, wn.fPts, ts); 2021a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2022a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2023a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 2024a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // FIXME: promote quad to cubic 2025a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 2026a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2027a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2028a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 2029a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com pts = CubicIntersect(wt.fPts, wn.fPts, ts); 2030a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2031a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2032a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2033a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 2034a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2035a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2036a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2037a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 2038f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2039a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com test->add(ts.fT[swap], pts, wt.verbIndex()); 2040a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com next->add(ts.fT[!swap], pts, wn.verbIndex()); 2041cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (wt.bottom() <= wn.bottom() ? wt.advance() : wn.advance()); 2042cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (nextPtr != lastPtr); 2043f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2044f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2045f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 20462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic InEdge** advanceEdges(SkTDArray<ActiveEdge>* activeEdges, 20476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge** currentPtr, InEdge** lastPtr, SkScalar y) { 20486008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge** testPtr = currentPtr - 1; 20496008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (++testPtr != lastPtr) { 20506008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if ((*testPtr)->fBounds.fBottom > y) { 20516008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com continue; 20526008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdges) { 20542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge* test = *testPtr; 20552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* activePtr = activeEdges->begin() - 1; 20562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* lastActive = activeEdges->end(); 20572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while (++activePtr != lastActive) { 20582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fWorkEdge.fEdge == test) { 20592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdges->remove(activePtr - activeEdges->begin()); 20602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com break; 20612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 20626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20636008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20646008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (testPtr == currentPtr) { 20656008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ++currentPtr; 20666008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20676008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 20686008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return currentPtr; 20696008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com} 20706008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com 20712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZE: inline? 20722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic HorizontalEdge** advanceHorizontal(HorizontalEdge** edge, SkScalar y) { 20732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com while ((*edge)->fY < y) { 20742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ++edge; 20752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 20762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return edge; 20772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 20782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 2079f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com// compute bottom taking into account any intersected edges 20802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic SkScalar computeInterceptBottom(SkTDArray<ActiveEdge>& activeEdges, 20812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y, SkScalar bottom) { 2082f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ActiveEdge* activePtr = activeEdges.begin() - 1; 2083f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com ActiveEdge* lastActive = activeEdges.end(); 2084f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com while (++activePtr != lastActive) { 2085f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const InEdge* test = activePtr->fWorkEdge.fEdge; 2086f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com if (!test->fContainsIntercepts) { 2087f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com continue; 2088f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2089f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com WorkEdge wt; 2090f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com wt.init(test); 2091f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 2092f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const Intercepts& intercepts = test->fIntercepts[wt.verbIndex()]; 20934917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (intercepts.fTopIntercepts > 1) { 20944917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com SkScalar yTop = wt.fPts[0].fY; 20954917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (yTop > y && bottom > yTop) { 20964917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com bottom = yTop; 20974917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 20984917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 20994917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (intercepts.fBottomIntercepts > 1) { 21004917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com SkScalar yBottom = wt.fPts[wt.verb()].fY; 21014917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (yBottom > y && bottom > yBottom) { 21024917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com bottom = yBottom; 21034917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 21044917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 2105f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const SkTDArray<double>& fTs = intercepts.fTs; 2106f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com size_t count = fTs.count(); 2107f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com for (size_t index = 0; index < count; ++index) { 2108a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkScalar yIntercept; 2109a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (wt.verb()) { 2110a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: { 2111a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = LineYAtT(wt.fPts, fTs[index]); 2112a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2113f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2114a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: { 2115a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = QuadYAtT(wt.fPts, fTs[index]); 2116a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2117a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2118a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: { 2119a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com yIntercept = CubicYAtT(wt.fPts, fTs[index]); 2120a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2121a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2122a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2123a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); // should never get here 2124a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2125a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (yIntercept > y && bottom > yIntercept) { 2126a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com bottom = yIntercept; 2127f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2128f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2129cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (wt.advance()); 2130f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2131198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#if DEBUG_BOTTOM 2132198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s bottom=%1.9g\n", __FUNCTION__, bottom); 2133198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 21342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 2135f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2136f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 2137d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic SkScalar findBottom(InEdge** currentPtr, 21382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** edgeListEnd, SkTDArray<ActiveEdge>* activeEdges, SkScalar y, 2139a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com bool /*asFill*/, InEdge**& testPtr) { 2140f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge* current = *currentPtr; 2141f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar bottom = current->fBounds.fBottom; 2142752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com 2143f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // find the list of edges that cross y 21446008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com InEdge* test = *testPtr; 21456008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (testPtr != edgeListEnd) { 21466008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkScalar testTop = test->fBounds.fTop; 21476008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (bottom <= testTop) { 2148f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com break; 2149f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 21506008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com SkScalar testBottom = test->fBounds.fBottom; 2151f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // OPTIMIZATION: Shortening the bottom is only interesting when filling 2152f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // and when the edge is to the left of a longer edge. If it's a framing 2153f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // edge, or part of the right, it won't effect the longer edges. 21546008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (testTop > y) { 21556008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bottom = testTop; 21566008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com break; 2157d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 21586008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (y < testBottom) { 21596008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (bottom > testBottom) { 21606008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com bottom = testBottom; 2161f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 21622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdges) { 21632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addToActive(*activeEdges, test); 21642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 2165f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 21666008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com test = *++testPtr; 2167f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2168198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#if DEBUG_BOTTOM 2169198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkDebugf("%s %d bottom=%1.9g\n", __FUNCTION__, activeEdges ? 2 : 1, bottom); 2170198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com#endif 2171f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com return bottom; 2172f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2173f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 2174f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comstatic void makeEdgeList(SkTArray<InEdge>& edges, InEdge& edgeSentinel, 2175f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<InEdge*>& edgeList) { 2176c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com size_t edgeCount = edges.count(); 2177c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com if (edgeCount == 0) { 2178c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com return; 2179c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 2180fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com int id = 0; 2181c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com for (size_t index = 0; index < edgeCount; ++index) { 2182fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com InEdge& edge = edges[index]; 2183fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com if (!edge.fWinding) { 2184fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com continue; 2185fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com } 2186fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edge.fID = ++id; 2187fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com *edgeList.append() = &edge; 2188c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } 2189c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com *edgeList.append() = &edgeSentinel; 2190cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com QSort<InEdge>(edgeList.begin(), edgeList.end() - 1); 2191f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 2192f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com 21932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic void makeHorizontalList(SkTDArray<HorizontalEdge>& edges, 21942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge& edgeSentinel, SkTDArray<HorizontalEdge*>& edgeList) { 21952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t edgeCount = edges.count(); 21962e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edgeCount == 0) { 21972e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return; 21982e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 21992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (size_t index = 0; index < edgeCount; ++index) { 22002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *edgeList.append() = &edges[index]; 22012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com edgeSentinel.fLeft = edgeSentinel.fRight = edgeSentinel.fY = SK_ScalarMax; 22032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com *edgeList.append() = &edgeSentinel; 22042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com QSort<HorizontalEdge>(edgeList.begin(), edgeList.end() - 1); 22052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 22066b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com 22076b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.comstatic void skipCoincidence(int lastWinding, int winding, int windingMask, 22086b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com ActiveEdge* activePtr, ActiveEdge* firstCoincident) { 22099f3e9a5a17a7546e1c5bfde1eb7e6e9c11870333caryclark@google.com if (((lastWinding & windingMask) == 0) ^ ((winding & windingMask) != 0)) { 22106b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com return; 2211d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 22122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: ? shouldn't this be if (lastWinding & windingMask) ? 22136b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (lastWinding) { 2214752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 2215752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d 1 set skip=false\n", __FUNCTION__, activePtr->ID()); 2216752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#endif 22176b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com activePtr->fSkip = false; 22186b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } else { 2219752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 2220752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s edge=%d 2 set skip=false\n", __FUNCTION__, firstCoincident->ID()); 2221752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com#endif 22226b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident->fSkip = false; 22236b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 22246b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com} 22256b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com 22266008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.comstatic void sortHorizontal(SkTDArray<ActiveEdge>& activeEdges, 22272e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<ActiveEdge*>& edgeList, SkScalar y) { 22286008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t edgeCount = activeEdges.count(); 22296008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com if (edgeCount == 0) { 22306008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com return; 22316008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 22322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 2233d88e0894d0156f4d427b812fec69bfba3eec7a8dcaryclark@google.com const int tab = 3; // FIXME: debugging only 22342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s y=%1.9g\n", __FUNCTION__, y); 22352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 22366008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com size_t index; 22376008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 0; index < edgeCount; ++index) { 22386008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge& activeEdge = activeEdges[index]; 22392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 22402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.calcLeft(y); 22412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // skip segments that don't span y 22422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdge.fAbove != activeEdge.fBelow) { 22432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com break; 22442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activeEdge.fDone) { 22462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 22472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d done\n", tab, "", activeEdge.ID()); 22482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 22492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com goto nextEdge; 22502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 22512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 22522e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d above==below\n", tab, "", activeEdge.ID()); 22532e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 22542e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (activeEdge.advanceT() || activeEdge.advance()); 22552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_SORT_HORIZONTAL 22562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%*s edge=%d above=(%1.9g,%1.9g) (%1.9g) below=(%1.9g,%1.9g)" 22572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com " (%1.9g)\n", tab, "", activeEdge.ID(), 22582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fAbove.fX, activeEdge.fAbove.fY, activeEdge.fTAbove, 22592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fBelow.fX, activeEdge.fBelow.fY, activeEdge.fTBelow); 22602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 22612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activeEdge.fSkip = activeEdge.fCloseCall = activeEdge.fFixBelow = false; 22626008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com *edgeList.append() = &activeEdge; 22632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comnextEdge: 22642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ; 22656008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com } 2266cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com QSort<ActiveEdge>(edgeList.begin(), edgeList.end() - 1); 22672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com} 22682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 22692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// remove coincident edges 22702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// OPTIMIZE: remove edges? This is tricky because the current logic expects 22712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// the winding count to be maintained while skipping coincident edges. In 22722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// addition to removing the coincident edges, the remaining edges would need 22732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// to have a different winding value, possibly different per intercept span. 22742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic SkScalar adjustCoincident(SkTDArray<ActiveEdge*>& edgeList, 22752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int windingMask, SkScalar y, SkScalar bottom, OutEdgeBuilder& outBuilder) 22762e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com{ 22772e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#if DEBUG_ADJUST_COINCIDENT 22782e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom); 22792e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 22802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t edgeCount = edgeList.count(); 22812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (edgeCount == 0) { 22822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 22832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 228478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ActiveEdge* activePtr, * nextPtr = edgeList[0]; 22852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com size_t index; 22862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool foundCoincident = false; 2287f25edfeac7c41aafc018c5de75185368838ab404caryclark@google.com size_t firstIndex = 0; 22882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 1; index < edgeCount; ++index) { 228978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr = nextPtr; 229078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com nextPtr = edgeList[index]; 2291fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com if (firstIndex != index - 1 && activePtr->fVerb > SkPath::kLine_Verb 2292fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com && nextPtr->fVerb == SkPath::kLine_Verb 2293fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com && activePtr->isUnordered(nextPtr)) { 2294fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // swap the line with the curve 2295fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // back up to the previous edge and retest 2296fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]); 2297fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkASSERT(index > 1); 2298fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com index -= 2; 2299fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com nextPtr = edgeList[index]; 2300fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com continue; 230178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 23022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bool closeCall = false; 23032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fCoincident = firstIndex; 230478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (activePtr->isCoincidentWith(nextPtr) 23052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com || (closeCall = activePtr->tooCloseToCall(nextPtr))) { 23062e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fSkip = nextPtr->fSkip = foundCoincident = true; 23072e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fCloseCall = nextPtr->fCloseCall = closeCall; 230878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } else if (activePtr->isUnordered(nextPtr)) { 230978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com foundCoincident = true; 23102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } else { 23112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com firstIndex = index; 23122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 231478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com nextPtr->fCoincident = firstIndex; 23152e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (!foundCoincident) { 23162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 23172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23186b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com int winding = 0; 231978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com nextPtr = edgeList[0]; 23206008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com for (index = 1; index < edgeCount; ++index) { 23212e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int priorWinding = winding; 23226b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com winding += activePtr->fWorkEdge.winding(); 232378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr = nextPtr; 232478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com nextPtr = edgeList[index]; 232578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(activePtr == edgeList[index - 1]); 232678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(nextPtr == edgeList[index]); 232778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (activePtr->fCoincident != nextPtr->fCoincident) { 232878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com continue; 232978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 233078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // the coincident edges may not have been sorted above -- advance 233178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // the edges and resort if needed 233278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // OPTIMIZE: if sorting is done incrementally as new edges are added 233378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // and not all at once as is done here, fold this test into the 233478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // current less than test. 233578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com while ((!activePtr->fSkip || !nextPtr->fSkip) 233678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com && activePtr->fCoincident == nextPtr->fCoincident) { 233778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (activePtr->swapUnordered(nextPtr, bottom)) { 233878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding -= activePtr->fWorkEdge.winding(); 233978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(activePtr == edgeList[index - 1]); 234078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(nextPtr == edgeList[index]); 234178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]); 234278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (--index == 0) { 234378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding += activePtr->fWorkEdge.winding(); 234478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com break; 234578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 234678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com // back up one 234778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr = edgeList[index - 1]; 234878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com continue; 234978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 235078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(activePtr == edgeList[index - 1]); 235178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(nextPtr == edgeList[index]); 235278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com break; 235378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 235478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (activePtr->fSkip && nextPtr->fSkip) { 23552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCloseCall ? activePtr->swapClose(nextPtr, 23562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com priorWinding, winding, windingMask) 23572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com : activePtr->swapCoincident(nextPtr, bottom)) { 23584917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com winding -= activePtr->fWorkEdge.winding(); 235978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(activePtr == edgeList[index - 1]); 236078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(nextPtr == edgeList[index]); 2361cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]); 2362cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com SkTSwap<ActiveEdge*>(activePtr, nextPtr); 23634917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com winding += activePtr->fWorkEdge.winding(); 236478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(activePtr == edgeList[index - 1]); 236578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkASSERT(nextPtr == edgeList[index]); 2366cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com } 23672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int firstCoincidentWinding = 0; 23702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com ActiveEdge* firstCoincident = NULL; 23712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com winding = 0; 23722e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr = edgeList[0]; 23732e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 1; index < edgeCount; ++index) { 23742e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com int priorWinding = winding; 23752e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com winding += activePtr->fWorkEdge.winding(); 237678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com nextPtr = edgeList[index]; 2377d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (activePtr->fSkip && nextPtr->fSkip 237878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com && activePtr->fCoincident == nextPtr->fCoincident) { 23796b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com if (!firstCoincident) { 23806b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident = activePtr; 23812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com firstCoincidentWinding = priorWinding; 23822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (activePtr->fCloseCall) { 23842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // If one of the edges has already been added to out as a non 23852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // coincident edge, trim it back to the top of this span 23862e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (outBuilder.trimLine(y, activePtr->ID())) { 23872e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->addTatYAbove(y); 2388752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2389752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 1 edge=%d y=%1.9g (was fYBottom=%1.9g)\n", 2390752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, activePtr->ID(), y, activePtr->fYBottom); 2391752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 23922e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->fYBottom = y; 23932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 23942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (outBuilder.trimLine(y, nextPtr->ID())) { 23952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->addTatYAbove(y); 2396752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2397752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 2 edge=%d y=%1.9g (was fYBottom=%1.9g)\n", 2398752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, nextPtr->ID(), y, nextPtr->fYBottom); 2399752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 24002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->fYBottom = y; 24012e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24022e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // add missing t values so edges can be the same length 24032e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar testY = activePtr->fBelow.fY; 24042e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com nextPtr->addTatYBelow(testY); 24052e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (bottom > testY && testY > y) { 2406752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2407752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 3 edge=%d bottom=%1.9g (was bottom=%1.9g)\n", 2408752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, activePtr->ID(), testY, bottom); 2409752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 24102e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = testY; 24112e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24122e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com testY = nextPtr->fBelow.fY; 24132e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr->addTatYBelow(testY); 24142e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (bottom > testY && testY > y) { 2415752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #if DEBUG_ADJUST_COINCIDENT 2416752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkDebugf("%s 4 edge=%d bottom=%1.9g (was bottom=%1.9g)\n", 2417752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com __FUNCTION__, nextPtr->ID(), testY, bottom); 2418752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com #endif 24192e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = testY; 24202e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24216b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 24222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } else if (firstCoincident) { 24232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com skipCoincidence(firstCoincidentWinding, winding, windingMask, 24242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com activePtr, firstCoincident); 24256b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident = NULL; 24266b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 24276008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com activePtr = nextPtr; 2428f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 24292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (firstCoincident) { 24306b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com winding += activePtr->fWorkEdge.winding(); 24312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com skipCoincidence(firstCoincidentWinding, winding, windingMask, activePtr, 24326b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com firstCoincident); 24336b9cfb34a3ed256a56571ebe3e39f5df940a16fbcaryclark@google.com } 24342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fix up the bottom for close call edges. OPTIMIZATION: maybe this could 24352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // be in the loop above, but moved here since loop above reads fBelow and 24362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // it felt unsafe to write it in that loop 24372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com for (index = 0; index < edgeCount; ++index) { 24382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com (edgeList[index])->fixBelow(); 24392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 24402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com return bottom; 2441f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 24426680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 2443f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com// stitch edge and t range that satisfies operation 2444d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic void stitchEdge(SkTDArray<ActiveEdge*>& edgeList, SkScalar 2445a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#if DEBUG_STITCH_EDGE 2446a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.comy 2447a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#endif 2448a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com, 2449752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com SkScalar bottom, int windingMask, bool fill, OutEdgeBuilder& outBuilder) { 2450f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int winding = 0; 24516008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge** activeHandle = edgeList.begin() - 1; 24526008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge** lastActive = edgeList.end(); 245378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#if DEBUG_STITCH_EDGE 2454a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com const int tab = 7; // FIXME: debugging only 245578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom); 245678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#endif 24576008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com while (++activeHandle != lastActive) { 24586008c656f90026a3b434938454fd2b67cf135e0acaryclark@google.com ActiveEdge* activePtr = *activeHandle; 2459f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const WorkEdge& wt = activePtr->fWorkEdge; 2460f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int lastWinding = winding; 2461f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com winding += wt.winding(); 246278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#if DEBUG_STITCH_EDGE 246378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkDebugf("%*s edge=%d lastWinding=%d winding=%d skip=%d close=%d" 246478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com " above=%1.9g below=%1.9g\n", 246578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com tab-4, "", activePtr->ID(), lastWinding, 246678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com winding, activePtr->fSkip, activePtr->fCloseCall, 246778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr->fTAbove, activePtr->fTBelow); 24682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com#endif 2469752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (activePtr->done(bottom)) { 247078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#if DEBUG_STITCH_EDGE 247178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkDebugf("%*s fDone=%d || fYBottom=%1.9g >= bottom\n", tab, "", 247278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr->fDone, activePtr->fYBottom); 247378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#endif 2474752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com continue; 2475cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } 2476c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com int opener = (lastWinding & windingMask) == 0; 2477c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com bool closer = (winding & windingMask) == 0; 2478c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com SkASSERT(!opener | !closer); 2479c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com bool inWinding = opener | closer; 2480a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkPoint clippedPts[4]; 24814917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com const SkPoint* clipped = NULL; 2482cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com bool moreToDo, aboveBottom; 2483f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 2484f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com double currentT = activePtr->t(); 2485f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com const SkPoint* points = wt.fPts; 2486cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com double nextT; 2487fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com SkPath::Verb verb = activePtr->fVerb; 24886680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com do { 2489cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com nextT = activePtr->nextT(); 2490d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // FIXME: obtuse: want efficient way to say 2491a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // !currentT && currentT != 1 || !nextT && nextT != 1 2492a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (currentT * nextT != 0 || currentT + nextT != 1) { 2493d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // OPTIMIZATION: if !inWinding, we only need 2494a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // clipped[1].fY 2495a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com switch (verb) { 2496a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kLine_Verb: 2497a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com LineSubDivide(points, currentT, nextT, clippedPts); 2498a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2499a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kQuad_Verb: 2500a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com QuadSubDivide(points, currentT, nextT, clippedPts); 2501a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2502a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com case SkPath::kCubic_Verb: 2503a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com CubicSubDivide(points, currentT, nextT, clippedPts); 2504a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 2505a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com default: 2506a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com SkASSERT(0); 2507a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com break; 25086680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com } 2509a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com clipped = clippedPts; 2510a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } else { 2511a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com clipped = points; 2512a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2513a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com if (inWinding && !activePtr->fSkip && (fill ? clipped[0].fY 2514a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com != clipped[verb].fY : clipped[0] != clipped[verb])) { 2515fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 2516fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s add%s %1.9g,%1.9g %1.9g,%1.9g edge=%d" 2517fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com " v=%d t=(%1.9g,%1.9g)\n", tab, "", 2518fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kUVerbStr[verb], clipped[0].fX, clipped[0].fY, 2519fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com clipped[verb].fX, clipped[verb].fY, 2520fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->ID(), 2521fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->fWorkEdge.fVerb 2522fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com - activePtr->fWorkEdge.fEdge->fVerbs.begin(), 2523fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com currentT, nextT); 2524fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 2525a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com outBuilder.addCurve(clipped, (SkPath::Verb) verb, 2526a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fWorkEdge.fEdge->fID, 2527a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fCloseCall); 2528cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } else { 2529fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#if DEBUG_STITCH_EDGE 2530fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com SkDebugf("%*s skip%s %1.9g,%1.9g %1.9g,%1.9g" 2531fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com " edge=%d v=%d t=(%1.9g,%1.9g)\n", tab, "", 2532fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com kUVerbStr[verb], clipped[0].fX, clipped[0].fY, 2533fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com clipped[verb].fX, clipped[verb].fY, 2534fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->ID(), 2535fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com activePtr->fWorkEdge.fVerb 2536fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com - activePtr->fWorkEdge.fEdge->fVerbs.begin(), 2537fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com currentT, nextT); 2538fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#endif 2539a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com } 2540a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // by advancing fAbove/fBelow, the next call to sortHorizontal 2541a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // will use these values if they're still valid instead of 2542a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com // recomputing 254378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com if (clipped[verb].fY > activePtr->fBelow.fY 2544fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com && bottom >= activePtr->fBelow.fY 2545fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com && verb == SkPath::kLine_Verb) { 2546a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fAbove = activePtr->fBelow; 2547fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com activePtr->fBelow = activePtr->fTangent = clipped[verb]; 254878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com activePtr->fTAbove = activePtr->fTBelow < 1 254978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com ? activePtr->fTBelow : 0; 2550a5764233aa6b207c4169fff7fccae567a160a0fdcaryclark@google.com activePtr->fTBelow = nextT; 2551f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2552f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com currentT = nextT; 2553cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com moreToDo = activePtr->advanceT(); 2554d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com activePtr->fYBottom = clipped[verb].fY; // was activePtr->fCloseCall ? bottom : 25552e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 25562e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // clearing the fSkip/fCloseCall bit here means that trailing edges 25572e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // fall out of sync, if one edge is long and another is a series of short pieces 25582e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // if fSkip/fCloseCall is set, need to recompute coincidence/too-close-to-call 25592e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // after advancing 25602e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // another approach would be to restrict bottom to smaller part of close call 25612e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // maybe this is already happening with coincidence when intersection is computed, 25622e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // and needs to be added to the close call computation as well 25632e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // this is hard to do because that the bottom is important is not known when 25642e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // the lines are intersected; only when the computation for edge sorting is done 25652e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // does the need for new bottoms become apparent. 25662e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // maybe this is good incentive to scrap the current sort and do an insertion 25672e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // sort that can take this into consideration when the x value is computed 25682e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com 25692e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // FIXME: initialized in sortHorizontal, cleared here as well so 25702e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // that next edge is not skipped -- but should skipped edges ever 25712e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // continue? (probably not) 2572752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com aboveBottom = clipped[verb].fY < bottom; 2573752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (clipped[0].fY != clipped[verb].fY) { 2574752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com activePtr->fSkip = false; 2575752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com activePtr->fCloseCall = false; 2576752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com aboveBottom &= !activePtr->fCloseCall; 257778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com } 257878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#if DEBUG_STITCH_EDGE 257978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com else { 2580752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com if (activePtr->fSkip || activePtr->fCloseCall) { 258178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com SkDebugf("%s skip or close == %1.9g\n", __FUNCTION__, 258278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com clippedPts[0].fY); 2583752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 2584752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com } 258578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#endif 2586cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while (moreToDo & aboveBottom); 2587cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com } while ((moreToDo || activePtr->advance()) & aboveBottom); 2588f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com } 2589f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com} 25906680fb1dc0ca55e5e3ddd41cb26dcd74fce28f6ecaryclark@google.com 2591a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#if DEBUG_DUMP 2592198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic void dumpEdgeList(const SkTDArray<InEdge*>& edgeList, 2593198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com const InEdge& edgeSentinel) { 2594198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com InEdge** debugPtr = edgeList.begin(); 2595198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com do { 2596198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com (*debugPtr++)->dump(); 2597198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } while (*debugPtr != &edgeSentinel); 2598198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com} 2599a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#else 2600a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.comstatic void dumpEdgeList(const SkTDArray<InEdge*>& , 2601a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com const InEdge& ) { 2602a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com} 2603a3f05facab01712a1b58e60a70b0dbdb90a39830caryclark@google.com#endif 2604198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com 2605f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.comvoid simplify(const SkPath& path, bool asFill, SkPath& simple) { 2606f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // returns 1 for evenodd, -1 for winding, regardless of inverse-ness 2607f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com int windingMask = (path.getFillType() & 1) ? 1 : -1; 2608f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com simple.reset(); 2609f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com simple.setFillType(SkPath::kEvenOdd_FillType); 2610f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // turn path into list of edges increasing in y 2611cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // if an edge is a quad or a cubic with a y extrema, note it, but leave it 2612cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // unbroken. Once we have a list, sort it, then walk the list (walk edges 2613cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // twice that have y extrema's on top) and detect crossings -- look for raw 2614cef7e3fc4bc6223ab0e42ed754e2a09028479c0bcaryclark@google.com // bounds that cross over, then tight bounds that cross 2615f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTArray<InEdge> edges; 26162e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge> horizontalEdges; 26172e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdgeBuilder builder(path, asFill, edges, horizontalEdges); 2618f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<InEdge*> edgeList; 2619f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge edgeSentinel; 2620fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edgeSentinel.reset(); 2621f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com makeEdgeList(edges, edgeSentinel, edgeList); 26222e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkTDArray<HorizontalEdge*> horizontalList; 26232e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge horizontalSentinel; 26242e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com makeHorizontalList(horizontalEdges, horizontalSentinel, horizontalList); 2625f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge** currentPtr = edgeList.begin(); 26264917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com if (!currentPtr) { 26274917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com return; 26284917f17bf6bd8bff7f4b03717dcb02561cf227c9caryclark@google.com } 26292e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // find all intersections between edges 26302e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// beyond looking for horizontal intercepts, we need to know if any active edges 26312e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// intersect edges below 'bottom', but above the active edge segment. 26322e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// maybe it makes more sense to compute all intercepts before doing anything 26332e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com// else, since the intercept list is long-lived, at least in the current design. 26342e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar y = (*currentPtr)->fBounds.fTop; 26352e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com HorizontalEdge** currentHorizontal = horizontalList.begin(); 26362e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com do { 26372e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set 26382e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com SkScalar bottom = findBottom(currentPtr, edgeList.end(), 26392e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com NULL, y, asFill, lastPtr); 26402e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (lastPtr > currentPtr) { 26412e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if (currentHorizontal) { 26422e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com if ((*currentHorizontal)->fY < SK_ScalarMax) { 26432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addBottomT(currentPtr, lastPtr, currentHorizontal); 26442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 26452e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentHorizontal = advanceHorizontal(currentHorizontal, bottom); 26462e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 26472e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com addIntersectingTs(currentPtr, lastPtr); 26482e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } 26492e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com y = bottom; 26502e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = advanceEdges(NULL, currentPtr, lastPtr, y); 26512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com } while (*currentPtr != &edgeSentinel); 2652198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // if a quadratic or cubic now has an intermediate T value, see if the Ts 2653198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // on either side cause the Y values to monotonically increase. If not, split 2654198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com // the curve at the new T. 2655fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com 2656fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // try an alternate approach which does not split curves or stitch edges 2657fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // (may still need adjustCoincident, though) 2658fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // the idea is to output non-intersecting contours, then figure out their 2659fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // respective winding contribution 2660fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // each contour will need to know whether it is CW or CCW, and then whether 2661fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // a ray from that contour hits any a contour that contains it. The ray can 2662fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // move to the left and then arbitrarily move up or down (as long as it never 2663d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // moves to the right) to find a reference sibling contour or containing 2664fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // contour. If the contour is part of an intersection, the companion contour 2665fa0588ff672564af1c235a63589573829035a60bcaryclark@google.com // that is part of the intersection can determine the containership. 2666198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (builder.containsCurves()) { 2667198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com currentPtr = edgeList.begin(); 2668198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com SkTArray<InEdge> splits; 2669198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com do { 2670fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com (*currentPtr)->splitInflectionPts(splits); 2671198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } while (*++currentPtr != &edgeSentinel); 2672198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com if (splits.count()) { 2673198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com for (int index = 0; index < splits.count(); ++index) { 2674198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com edges.push_back(splits[index]); 2675198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2676fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com edgeList.reset(); 2677198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com makeEdgeList(edges, edgeSentinel, edgeList); 2678198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2679198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com } 2680198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com dumpEdgeList(edgeList, edgeSentinel); 2681f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com // walk the sorted edges from top to bottom, computing accumulated winding 2682f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkTDArray<ActiveEdge> activeEdges; 2683f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com OutEdgeBuilder outBuilder(asFill); 26842e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = edgeList.begin(); 26852e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com y = (*currentPtr)->fBounds.fTop; 2686f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com do { 2687f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set 2688f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com SkScalar bottom = findBottom(currentPtr, edgeList.end(), 26892e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com &activeEdges, y, asFill, lastPtr); 2690c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com if (lastPtr > currentPtr) { 26912e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = computeInterceptBottom(activeEdges, y, bottom); 2692c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com SkTDArray<ActiveEdge*> activeEdgeList; 26932e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com sortHorizontal(activeEdges, activeEdgeList, y); 26942e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com bottom = adjustCoincident(activeEdgeList, windingMask, y, bottom, 26952e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com outBuilder); 2696752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com stitchEdge(activeEdgeList, y, bottom, windingMask, asFill, outBuilder); 2697c17972e7acc784553445adc18f608a8c4b1beac8caryclark@google.com } 2698c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com y = bottom; 26992e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com // OPTIMIZATION: as edges expire, InEdge allocations could be released 27002e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com currentPtr = advanceEdges(&activeEdges, currentPtr, lastPtr, y); 2701c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com } while (*currentPtr != &edgeSentinel); 2702c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com // assemble output path from string of pts, verbs 2703f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com outBuilder.bridge(); 2704f8b000d7ae32ac9bb67c8e33cae500cac7407d26caryclark@google.com outBuilder.assemble(simple); 2705c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com} 2706