1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #include "LoopBlinnPathProcessor.h" 29 30 #include "FloatPoint.h" 31 #include "FloatRect.h" 32 #include "LoopBlinnClassifier.h" 33 #include "LoopBlinnConstants.h" 34 #include "LoopBlinnLocalTriangulator.h" 35 #include "LoopBlinnMathUtils.h" 36 #include "LoopBlinnPathCache.h" 37 #include "LoopBlinnTextureCoords.h" 38 #include "PODArena.h" 39 #include "PODIntervalTree.h" 40 #include "Path.h" 41 #include "internal_glu.h" 42 #include <algorithm> 43 #include <wtf/Assertions.h> 44 #include <wtf/FastMalloc.h> 45 #include <wtf/UnusedParam.h> 46 47 48 #if USE(SKIA) 49 #include "SkGeometry.h" 50 #include "SkPath.h" 51 #include "SkScalar.h" 52 #else 53 // Must port to your platform. 54 #endif 55 56 namespace WebCore { 57 58 using LoopBlinnMathUtils::XRay; 59 using LoopBlinnMathUtils::chopCubicAt; 60 using LoopBlinnMathUtils::numXRayCrossingsForCubic; 61 using LoopBlinnMathUtils::trianglesOverlap; 62 using LoopBlinnMathUtils::xRayCrossesLine; 63 using LoopBlinnPathProcessorImplementation::Contour; 64 using LoopBlinnPathProcessorImplementation::Segment; 65 66 namespace { 67 68 #ifndef NDEBUG 69 String valueToString(const FloatRect& arg) 70 { 71 StringBuilder builder; 72 builder.append("[FloatRect x="); 73 builder.append(String::number(arg.x())); 74 builder.append(" y="); 75 builder.append(String::number(arg.y())); 76 builder.append(" maxX="); 77 builder.append(String::number(arg.maxX())); 78 builder.append(" maxY="); 79 builder.append(String::number(arg.maxY())); 80 builder.append("]"); 81 return builder.toString(); 82 } 83 #endif 84 85 struct SweepData; 86 87 } // anonymous namespace 88 89 namespace LoopBlinnPathProcessorImplementation { 90 class Segment; 91 } 92 93 #ifndef NDEBUG 94 // Routines needed to print the types of IntervalNodes we instantiate 95 // in this file. 96 template <> 97 struct ValueToString<float> { 98 static String string(const float& value) 99 { 100 return String::number(value); 101 } 102 }; 103 104 template <> 105 struct ValueToString<SweepData*> { 106 static String string(SweepData* const& value) 107 { 108 return String::format("0x%p", value); 109 } 110 }; 111 112 template <> 113 struct ValueToString<LoopBlinnPathProcessorImplementation::Segment*> { 114 static String string(LoopBlinnPathProcessorImplementation::Segment* const& value) 115 { 116 return String::format("0x%p", value); 117 } 118 }; 119 #endif 120 121 namespace LoopBlinnPathProcessorImplementation { 122 123 //---------------------------------------------------------------------- 124 // Segment 125 // 126 127 // Describes a segment of the path: either a cubic or a line segment. 128 // These are stored in a doubly linked list to speed up curve 129 // subdivision, which occurs due to either rendering artifacts in the 130 // loop case or due to overlapping triangles. 131 class Segment { 132 WTF_MAKE_NONCOPYABLE(Segment); 133 public: 134 enum Kind { 135 Cubic, 136 Line 137 }; 138 139 // No-argument constructor allows construction by the PODArena class. 140 Segment() 141 : m_arena(0) 142 , m_kind(Cubic) 143 , m_prev(0) 144 , m_next(0) 145 , m_contour(0) 146 , m_triangulator(0) 147 , m_markedForSubdivision(false) 148 { 149 } 150 151 // Initializer for cubic curve segments. 152 void setup(PODArena* arena, 153 Contour* contour, 154 FloatPoint cp0, 155 FloatPoint cp1, 156 FloatPoint cp2, 157 FloatPoint cp3) 158 { 159 m_arena = arena; 160 m_contour = contour; 161 m_kind = Cubic; 162 m_points[0] = cp0; 163 m_points[1] = cp1; 164 m_points[2] = cp2; 165 m_points[3] = cp3; 166 computeBoundingBox(); 167 } 168 169 // Initializer for line segments. 170 void setup(PODArena* arena, 171 Contour* contour, 172 FloatPoint p0, 173 FloatPoint p1) 174 { 175 m_arena = arena; 176 m_contour = contour; 177 m_kind = Line; 178 m_points[0] = p0; 179 m_points[1] = p1; 180 computeBoundingBox(); 181 } 182 183 Kind kind() const { return m_kind; } 184 185 // Returns the i'th control point, 0 <= i < 4. 186 const FloatPoint& getPoint(int i) 187 { 188 ASSERT(i >= 0 && i < 4); 189 return m_points[i]; 190 } 191 192 Segment* next() const { return m_next; } 193 Segment* prev() const { return m_prev; } 194 195 void setNext(Segment* next) { m_next = next; } 196 void setPrev(Segment* prev) { m_prev = prev; } 197 198 // The contour this segment belongs to. 199 Contour* contour() const { return m_contour; } 200 201 // Subdivides the current segment at the given parameter value (0 <= 202 // t <= 1) and replaces it with the two newly created Segments in 203 // the linked list, if possible. Returns a pointer to the leftmost 204 // Segment. 205 Segment* subdivide(float param) 206 { 207 FloatPoint dst[7]; 208 chopCubicAt(m_points, dst, param); 209 Segment* left = m_arena->allocateObject<Segment>(); 210 Segment* right = m_arena->allocateObject<Segment>(); 211 left->setup(m_arena, m_contour, dst[0], dst[1], dst[2], dst[3]); 212 right->setup(m_arena, m_contour, dst[3], dst[4], dst[5], dst[6]); 213 left->setNext(right); 214 right->setPrev(left); 215 // Try to set up a link between "this->prev()" and "left". 216 if (prev()) { 217 left->setPrev(prev()); 218 prev()->setNext(left); 219 } 220 // Try to set up a link between "this->next()" and "right". 221 Segment* n = next(); 222 if (n) { 223 right->setNext(n); 224 n->setPrev(right); 225 } 226 // Set up a link between "this" and "left"; this is only to 227 // provide a certain amount of continuity during forward iteration. 228 setNext(left); 229 return left; 230 } 231 232 // Subdivides the current segment at the halfway point and replaces 233 // it with the two newly created Segments in the linked list, if 234 // possible. Returns a pointer to the leftmost Segment. 235 Segment* subdivide() { return subdivide(0.5f); } 236 237 const FloatRect& boundingBox() const { return m_boundingBox; } 238 239 // Computes the number of times a query line starting at the given 240 // point and extending to x=+infinity crosses this segment. Outgoing 241 // "ambiguous" argument indicates whether the query intersected an 242 // endpoint or tangent point of the segment, indicating that another 243 // query point is preferred. 244 int numCrossingsForXRay(const XRay& xRay, bool& ambiguous) const 245 { 246 if (m_kind == Cubic) 247 // Should consider caching the monotonic cubics. 248 return numXRayCrossingsForCubic(xRay, m_points, ambiguous); 249 250 return xRayCrossesLine(xRay, m_points, ambiguous) ? 1 : 0; 251 } 252 253 // Performs a local triangulation of the control points in this 254 // segment. This operation only makes sense for cubic type segments. 255 // texCoords may be null when the klm coordinates have not been 256 // computed yet. 257 void triangulate(LoopBlinnLocalTriangulator::InsideEdgeComputation computeInsideEdges, 258 const LoopBlinnTextureCoords::Result* texCoords); 259 260 // Returns the number of control point triangles associated with 261 // this segment. 262 int numberOfTriangles() const 263 { 264 if (!m_triangulator) 265 return 0; 266 return m_triangulator->numberOfTriangles(); 267 } 268 269 // Fetches the given control point triangle for this segment. 270 LoopBlinnLocalTriangulator::Triangle* getTriangle(int index) 271 { 272 ASSERT(m_triangulator); 273 return m_triangulator->getTriangle(index); 274 } 275 276 // Number of vertices along the inside edge of this segment. This 277 // can be called either for line or cubic type segments. 278 int numberOfInteriorVertices() const 279 { 280 if (m_kind == Cubic) { 281 if (m_triangulator) 282 return m_triangulator->numberOfInteriorVertices(); 283 284 return 0; 285 } 286 287 return 2; 288 } 289 290 // Returns the given interior vertex, 0 <= index < numberOfInteriorVertices(). 291 FloatPoint getInteriorVertex(int index) const 292 { 293 ASSERT(index >= 0 && index < numberOfInteriorVertices()); 294 if (m_kind == Cubic) { 295 FloatPoint res; 296 if (m_triangulator) { 297 LoopBlinnLocalTriangulator::Vertex* vertex = m_triangulator->getInteriorVertex(index); 298 if (vertex) 299 res.set(vertex->xyCoordinates().x(), vertex->xyCoordinates().y()); 300 } 301 return res; 302 } 303 304 return m_points[index]; 305 } 306 307 // State to assist with curve subdivision. 308 bool markedForSubdivision() const { return m_markedForSubdivision; } 309 void setMarkedForSubdivision(bool markedForSubdivision) { m_markedForSubdivision = markedForSubdivision; } 310 311 #ifndef NDEBUG 312 // Suppport for printing Segments. 313 String toString() const 314 { 315 StringBuilder builder; 316 builder.append("[Segment kind="); 317 builder.append(kind() == Line ? "line" : "cubic"); 318 builder.append(" boundingBox="); 319 builder.append(valueToString(boundingBox())); 320 builder.append(" contour=0x"); 321 builder.append(String::format("%p", contour())); 322 builder.append(" markedForSubdivision="); 323 builder.append(markedForSubdivision() ? "true" : "false"); 324 builder.append("]"); 325 return builder.toString(); 326 } 327 #endif 328 329 private: 330 // Computes the bounding box of this Segment. 331 void computeBoundingBox() 332 { 333 switch (m_kind) { 334 case Cubic: 335 m_boundingBox.fitToPoints(m_points[0], m_points[1], m_points[2], m_points[3]); 336 break; 337 338 case Line: 339 m_boundingBox.fitToPoints(m_points[0], m_points[1]); 340 break; 341 } 342 } 343 344 PODArena* m_arena; 345 Kind m_kind; 346 FloatPoint m_points[4]; 347 Segment* m_prev; 348 Segment* m_next; 349 Contour* m_contour; 350 FloatRect m_boundingBox; 351 LoopBlinnLocalTriangulator* m_triangulator; 352 bool m_markedForSubdivision; 353 }; 354 355 //---------------------------------------------------------------------- 356 // Contour 357 // 358 359 // Describes a closed contour of the path. 360 class Contour { 361 WTF_MAKE_NONCOPYABLE(Contour); 362 public: 363 Contour() 364 { 365 m_first = &m_sentinel; 366 m_first->setNext(m_first); 367 m_first->setPrev(m_first); 368 m_isOrientedCounterClockwise = true; 369 m_boundingBoxDirty = false; 370 m_fillSide = LoopBlinnConstants::RightSide; 371 } 372 373 void add(Segment* segment) 374 { 375 if (m_first == &m_sentinel) { 376 // First element is the sentinel. Replace it with the incoming 377 // segment. 378 segment->setNext(m_first); 379 segment->setPrev(m_first); 380 m_first->setNext(segment); 381 m_first->setPrev(segment); 382 m_first = segment; 383 } else { 384 // m_first->prev() is the sentinel. 385 ASSERT(m_first->prev() == &m_sentinel); 386 Segment* last = m_sentinel.prev(); 387 last->setNext(segment); 388 segment->setPrev(last); 389 segment->setNext(&m_sentinel); 390 m_sentinel.setPrev(segment); 391 } 392 m_boundingBoxDirty = true; 393 } 394 395 // Subdivides the given segment at the given parametric value. 396 // Returns a pointer to the first of the two portions of the 397 // subdivided segment. 398 Segment* subdivide(Segment* segment, float param) 399 { 400 Segment* left = segment->subdivide(param); 401 if (m_first == segment) 402 m_first = left; 403 return left; 404 } 405 406 // Subdivides the given segment at the halfway point. Returns a 407 // pointer to the first of the two portions of the subdivided 408 // segment. 409 Segment* subdivide(Segment* segment) 410 { 411 Segment* left = segment->subdivide(); 412 if (m_first == segment) 413 m_first = left; 414 return left; 415 } 416 417 // Returns the first segment in the contour for iteration. 418 Segment* begin() const { return m_first; } 419 420 // Returns the last segment in the contour for iteration. Callers 421 // should not iterate over this segment. In other words: 422 // for (Segment* cur = contour->begin(); 423 // cur != contour->end(); 424 // cur = cur->next()) { 425 // // .. process cur ... 426 // } 427 Segment* end() 428 { 429 ASSERT(m_first->prev() == &m_sentinel); 430 return &m_sentinel; 431 } 432 433 bool isOrientedCounterClockwise() const { return m_isOrientedCounterClockwise; } 434 void setIsOrientedCounterClockwise(bool isOrientedCounterClockwise) { m_isOrientedCounterClockwise = isOrientedCounterClockwise; } 435 436 const FloatRect& boundingBox() 437 { 438 if (m_boundingBoxDirty) { 439 bool first = true; 440 for (Segment* cur = begin(); cur != end(); cur = cur->next()) { 441 if (first) 442 m_boundingBox = cur->boundingBox(); 443 else 444 m_boundingBox.unite(cur->boundingBox()); 445 first = false; 446 } 447 448 m_boundingBoxDirty = false; 449 } 450 return m_boundingBox; 451 } 452 453 // Returns which side of this contour is filled. 454 LoopBlinnConstants::FillSide fillSide() const 455 { 456 return m_fillSide; 457 } 458 459 void setFillSide(LoopBlinnConstants::FillSide fillSide) 460 { 461 m_fillSide = fillSide; 462 } 463 464 private: 465 // The start of the segment chain. The segments are kept in a 466 // circular doubly linked list for rapid access to the beginning and 467 // end. 468 Segment* m_first; 469 470 // The sentinel element at the end of the chain, needed for 471 // reasonable iteration semantics. 472 Segment m_sentinel; 473 474 bool m_isOrientedCounterClockwise; 475 476 FloatRect m_boundingBox; 477 bool m_boundingBoxDirty; 478 479 // Which side of this contour should be filled. 480 LoopBlinnConstants::FillSide m_fillSide; 481 }; 482 483 //---------------------------------------------------------------------- 484 // Segment 485 // 486 487 // Definition of Segment::triangulate(), which must come after 488 // declaration of Contour. 489 void Segment::triangulate(LoopBlinnLocalTriangulator::InsideEdgeComputation computeInsideEdges, 490 const LoopBlinnTextureCoords::Result* texCoords) 491 { 492 ASSERT(m_kind == Cubic); 493 if (!m_triangulator) 494 m_triangulator = m_arena->allocateObject<LoopBlinnLocalTriangulator>(); 495 m_triangulator->reset(); 496 for (int i = 0; i < 4; i++) { 497 LoopBlinnLocalTriangulator::Vertex* vertex = m_triangulator->getVertex(i); 498 if (texCoords) { 499 vertex->set(getPoint(i).x(), 500 getPoint(i).y(), 501 texCoords->klmCoordinates[i].x(), 502 texCoords->klmCoordinates[i].y(), 503 texCoords->klmCoordinates[i].z()); 504 } else { 505 vertex->set(getPoint(i).x(), 506 getPoint(i).y(), 507 // No texture coordinates yet 508 0, 0, 0); 509 } 510 } 511 m_triangulator->triangulate(computeInsideEdges, contour()->fillSide()); 512 } 513 514 } // namespace LoopBlinnPathProcessorImplementation 515 516 //---------------------------------------------------------------------- 517 // LoopBlinnPathProcessor 518 // 519 520 LoopBlinnPathProcessor::LoopBlinnPathProcessor() 521 : m_arena(PODArena::create()) 522 #ifndef NDEBUG 523 , m_verboseLogging(false) 524 #endif 525 { 526 } 527 528 LoopBlinnPathProcessor::LoopBlinnPathProcessor(PassRefPtr<PODArena> arena) 529 : m_arena(arena) 530 #ifndef NDEBUG 531 , m_verboseLogging(false) 532 #endif 533 { 534 } 535 536 LoopBlinnPathProcessor::~LoopBlinnPathProcessor() 537 { 538 } 539 540 void LoopBlinnPathProcessor::process(const Path& path, LoopBlinnPathCache& cache) 541 { 542 buildContours(path); 543 544 // Run plane-sweep algorithm to determine overlaps of control point 545 // curves and subdivide curves appropriately. 546 subdivideCurves(); 547 548 // Determine orientations of countours. Based on orientation and the 549 // number of curve crossings at a random point on the contour, 550 // determine whether to fill the left or right side of the contour. 551 determineSidesToFill(); 552 553 // Classify curves, compute texture coordinates and subdivide as 554 // necessary to eliminate rendering artifacts. Do the final 555 // triangulation of the curve segments, determining the path along 556 // the interior of the shape. 557 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 558 Contour* cur = *iter; 559 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 560 if (seg->kind() == Segment::Cubic) { 561 LoopBlinnClassifier::Result classification = LoopBlinnClassifier::classify(seg->getPoint(0), 562 seg->getPoint(1), 563 seg->getPoint(2), 564 seg->getPoint(3)); 565 #ifndef NDEBUG 566 if (m_verboseLogging) 567 LOG_ERROR("Classification: %d", (int) classification.curveType); 568 #endif 569 LoopBlinnTextureCoords::Result texCoords = 570 LoopBlinnTextureCoords::compute(classification, cur->fillSide()); 571 if (texCoords.hasRenderingArtifact) { 572 // FIXME: there is a problem where the algorithm 573 // sometimes fails to converge when splitting at the 574 // subdivision parameter value. For the time being, 575 // split halfway. 576 cur->subdivide(seg); 577 // Next iteration will handle the newly subdivided curves 578 } else { 579 if (!texCoords.isLineOrPoint) { 580 seg->triangulate(LoopBlinnLocalTriangulator::ComputeInsideEdges, &texCoords); 581 for (int i = 0; i < seg->numberOfTriangles(); i++) { 582 LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i); 583 for (int j = 0; j < 3; j++) { 584 LoopBlinnLocalTriangulator::Vertex* vert = triangle->getVertex(j); 585 cache.addVertex(vert->xyCoordinates().x(), 586 vert->xyCoordinates().y(), 587 vert->klmCoordinates().x(), 588 vert->klmCoordinates().y(), 589 vert->klmCoordinates().z()); 590 } 591 } 592 #ifdef LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES 593 // Show the end user the interior edges as well 594 for (int i = 1; i < seg->numberOfInteriorVertices(); i++) { 595 FloatPoint vert = seg->getInteriorVertex(i); 596 // Duplicate previous vertex to be able to draw GL_LINES 597 FloatPoint prev = seg->getInteriorVertex(i - 1); 598 cache.addInteriorEdgeVertex(prev.x(), prev.y()); 599 cache.addInteriorEdgeVertex(vert.x(), vert.y()); 600 } 601 #endif // LOOP_BLINN_PATH_CACHE_DEBUG_INTERIOR_EDGES 602 } 603 } 604 } 605 } 606 } 607 608 // Run the interior paths through a tessellation algorithm 609 // supporting multiple contours. 610 tessellateInterior(cache); 611 } 612 613 void LoopBlinnPathProcessor::buildContours(const Path& path) 614 { 615 // Clear out the contours 616 m_contours.clear(); 617 #if USE(SKIA) 618 SkPath::Iter iter(*path.platformPath(), false); 619 SkPoint points[4]; 620 SkPath::Verb verb; 621 Contour* contour = 0; 622 SkPoint curPoint = { 0 }; 623 SkPoint moveToPoint = { 0 }; 624 do { 625 verb = iter.next(points); 626 if (verb != SkPath::kMove_Verb) { 627 if (!contour) { 628 contour = m_arena->allocateObject<Contour>(); 629 m_contours.append(contour); 630 } 631 } 632 switch (verb) { 633 case SkPath::kMove_Verb: { 634 contour = m_arena->allocateObject<Contour>(); 635 m_contours.append(contour); 636 curPoint = points[0]; 637 moveToPoint = points[0]; 638 #ifndef NDEBUG 639 if (m_verboseLogging) 640 LOG_ERROR("MoveTo (%f, %f)", points[0].fX, points[0].fY); 641 #endif 642 break; 643 } 644 case SkPath::kLine_Verb: { 645 Segment* segment = m_arena->allocateObject<Segment>(); 646 if (iter.isCloseLine()) { 647 segment->setup(m_arena.get(), contour, curPoint, points[1]); 648 #ifndef NDEBUG 649 if (m_verboseLogging) 650 LOG_ERROR("CloseLineTo (%f, %f), (%f, %f)", curPoint.fX, curPoint.fY, points[1].fX, points[1].fY); 651 #endif 652 contour->add(segment); 653 contour = 0; 654 } else { 655 segment->setup(m_arena.get(), contour, points[0], points[1]); 656 #ifndef NDEBUG 657 if (m_verboseLogging) 658 LOG_ERROR("LineTo (%f, %f), (%f, %f)", points[0].fX, points[0].fY, points[1].fX, points[1].fY); 659 #endif 660 contour->add(segment); 661 curPoint = points[1]; 662 } 663 break; 664 } 665 case SkPath::kQuad_Verb: { 666 // Need to degree elevate the quadratic into a cubic 667 SkPoint cubic[4]; 668 SkConvertQuadToCubic(points, cubic); 669 Segment* segment = m_arena->allocateObject<Segment>(); 670 segment->setup(m_arena.get(), contour, 671 cubic[0], cubic[1], cubic[2], cubic[3]); 672 #ifndef NDEBUG 673 if (m_verboseLogging) 674 LOG_ERROR("Quad->CubicTo (%f, %f), (%f, %f), (%f, %f), (%f, %f)", cubic[0].fX, cubic[0].fY, cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY); 675 #endif 676 contour->add(segment); 677 curPoint = cubic[3]; 678 break; 679 } 680 case SkPath::kCubic_Verb: { 681 Segment* segment = m_arena->allocateObject<Segment>(); 682 segment->setup(m_arena.get(), contour, points[0], points[1], points[2], points[3]); 683 #ifndef NDEBUG 684 if (m_verboseLogging) 685 LOG_ERROR("CubicTo (%f, %f), (%f, %f), (%f, %f), (%f, %f)", points[0].fX, points[0].fY, points[1].fX, points[1].fY, points[2].fX, points[2].fY, points[3].fX, points[3].fY); 686 #endif 687 contour->add(segment); 688 curPoint = points[3]; 689 break; 690 } 691 case SkPath::kClose_Verb: { 692 Segment* segment = m_arena->allocateObject<Segment>(); 693 segment->setup(m_arena.get(), contour, curPoint, moveToPoint); 694 #ifndef NDEBUG 695 if (m_verboseLogging) 696 LOG_ERROR("Close (%f, %f) -> (%f, %f)", curPoint.fX, curPoint.fY, moveToPoint.fX, moveToPoint.fY); 697 #endif 698 contour->add(segment); 699 contour = 0; 700 } 701 case SkPath::kDone_Verb: 702 break; 703 } 704 } while (verb != SkPath::kDone_Verb); 705 #else // !USE(SKIA) 706 UNUSED_PARAM(path); 707 // Must port to your platform. 708 ASSERT_NOT_REACHED(); 709 #endif 710 } 711 712 #ifndef NDEBUG 713 Vector<Segment*> LoopBlinnPathProcessor::allSegmentsOverlappingY(Contour* queryContour, float x, float y) 714 { 715 Vector<Segment*> res; 716 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 717 Contour* cur = *iter; 718 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 719 const FloatRect& boundingBox = seg->boundingBox(); 720 if (boundingBox.y() <= y && y <= boundingBox.maxY()) 721 res.append(seg); 722 } 723 } 724 return res; 725 } 726 #endif 727 728 // Uncomment this to debug the orientation computation. 729 // #define GPU_PATH_PROCESSOR_DEBUG_ORIENTATION 730 731 void LoopBlinnPathProcessor::determineSidesToFill() 732 { 733 // Loop and Blinn's algorithm can only easily emulate the even/odd 734 // fill rule, and only for non-intersecting curves. We can determine 735 // which side of each curve segment to fill based on its 736 // clockwise/counterclockwise orientation and how many other 737 // contours surround it. 738 739 // To optimize the query of all curve segments intersecting a 740 // horizontal line going to x=+infinity, we build up an interval 741 // tree whose keys are the y extents of the segments. 742 PODIntervalTree<float, Segment*> tree(m_arena); 743 typedef PODIntervalTree<float, Segment*>::IntervalType IntervalType; 744 745 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 746 Contour* cur = *iter; 747 determineOrientation(cur); 748 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 749 const FloatRect& boundingBox = seg->boundingBox(); 750 tree.add(tree.createInterval(boundingBox.y(), boundingBox.maxY(), seg)); 751 } 752 } 753 754 // Now iterate through the contours and pick a random segment (in 755 // this case we use the first) and a random point on that segment. 756 // Find all segments from other contours which intersect this one 757 // and count the number of crossings a horizontal line to 758 // x=+infinity makes with those contours. This combined with the 759 // orientation of the curve tells us which side to fill -- again, 760 // assuming an even/odd fill rule, which is all we can easily 761 // handle. 762 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 763 Contour* cur = *iter; 764 765 bool ambiguous = true; 766 int numCrossings = 0; 767 768 // For each contour, attempt to find a point on the contour which, 769 // when we cast an XRay, does not intersect the other contours at 770 // an ambiguous point (the junction between two curves or at a 771 // tangent point). Ambiguous points make the determination of 772 // whether this contour is contained within another fragile. Note 773 // that this loop is only an approximation to the selection of a 774 // good casting point. We could as well evaluate a segment to 775 // determine a point upon it. 776 for (Segment* seg = cur->begin(); 777 ambiguous && seg != cur->end(); 778 seg = seg->next()) { 779 numCrossings = 0; 780 // We use a zero-sized vertical interval for the query. 781 Vector<IntervalType> overlaps = tree.allOverlaps(tree.createInterval(seg->getPoint(0).y(), 782 seg->getPoint(0).y(), 783 0)); 784 #if defined(GPU_PATH_PROCESSOR_DEBUG_ORIENTATION) && !defined(NDEBUG) 785 Vector<Segment*> slowOverlaps = allSegmentsOverlappingY(cur, seg->getPoint(0).x(), seg->getPoint(0).y()); 786 if (overlaps.size() != slowOverlaps.size()) { 787 LOG_ERROR("For query point (%f, %f) on contour 0x%p:", seg->getPoint(0).x(), seg->getPoint(0).y(), cur); 788 LOG_ERROR(" overlaps:"); 789 for (size_t i = 0; i < overlaps.size(); i++) 790 LOG_ERROR(" %d: %s", i+1, overlaps[i].data()->toString().ascii().data()); 791 LOG_ERROR(" slowOverlaps:"); 792 for (size_t i = 0; i < slowOverlaps.size(); i++) 793 LOG_ERROR(" %d: %s", (i+1) slowOverlaps[i]->toString()); 794 LOG_ERROR("Interval tree:"); 795 tree.dump(); 796 } 797 ASSERT(overlaps.size() == slowOverlaps.size()); 798 #endif // defined(GPU_PATH_PROCESSOR_DEBUG_ORIENTATION) && !defined(NDEBUG) 799 for (Vector<IntervalType>::iterator iter = overlaps.begin(); iter != overlaps.end(); ++iter) { 800 const IntervalType& interval = *iter; 801 Segment* querySegment = interval.data(); 802 // Ignore segments coming from the same contour. 803 if (querySegment->contour() != cur) { 804 // Only perform queries that can affect the computation. 805 const FloatRect& boundingBox = querySegment->contour()->boundingBox(); 806 if (seg->getPoint(0).x() >= boundingBox.x() 807 && seg->getPoint(0).x() <= boundingBox.maxX()) { 808 numCrossings += querySegment->numCrossingsForXRay(seg->getPoint(0), 809 ambiguous); 810 if (ambiguous) { 811 #ifndef NDEBUG 812 if (m_verboseLogging) { 813 LOG_ERROR("Ambiguous intersection query at point (%f, %f)", seg->getPoint(0).x(), seg->getPoint(0).y()); 814 LOG_ERROR("Query segment: %s", querySegment->toString().ascii().data()); 815 } 816 #endif 817 break; // Abort iteration over overlaps. 818 } 819 } 820 } 821 } 822 } // for (Segment* seg = cur->begin(); ... 823 824 cur->setFillSide((cur->isOrientedCounterClockwise() ^ (numCrossings & 1)) ? LoopBlinnConstants::LeftSide : LoopBlinnConstants::RightSide); 825 } 826 } 827 828 void LoopBlinnPathProcessor::determineOrientation(Contour* contour) 829 { 830 // Determine signed area of the polygon represented by the points 831 // along the segments. Consider this an approximation to the true 832 // orientation of the polygon; it probably won't handle 833 // self-intersecting curves correctly. 834 // 835 // There is also a pretty basic assumption here that the contour is 836 // closed. 837 float signedArea = 0; 838 for (Segment* seg = contour->begin(); 839 seg != contour->end(); 840 seg = seg->next()) { 841 int limit = (seg->kind() == Segment::Cubic) ? 4 : 2; 842 for (int i = 1; i < limit; i++) { 843 const FloatPoint& prevPoint = seg->getPoint(i - 1); 844 const FloatPoint& point = seg->getPoint(i); 845 float curArea = prevPoint.x() * point.y() - prevPoint.y() * point.x(); 846 #ifndef NDEBUG 847 if (m_verboseLogging) 848 LOG_ERROR("Adding to signed area (%f, %f) -> (%f, %f) = %f", prevPoint.x(), prevPoint.y(), point.x(), point.y(), curArea); 849 #endif 850 signedArea += curArea; 851 } 852 } 853 854 if (signedArea > 0) 855 contour->setIsOrientedCounterClockwise(true); 856 else 857 contour->setIsOrientedCounterClockwise(false); 858 } 859 860 namespace { 861 862 //---------------------------------------------------------------------- 863 // Classes and typedefs needed for curve subdivision. These can't be scoped 864 // within the subdivideCurves() method itself, because templates then fail 865 // to instantiate. 866 867 // The user data which is placed in the PODIntervalTree. 868 struct SweepData { 869 SweepData() 870 : triangle(0) 871 , segment(0) 872 { 873 } 874 875 // The triangle this interval is associated with 876 LoopBlinnLocalTriangulator::Triangle* triangle; 877 // The segment the triangle is associated with 878 Segment* segment; 879 }; 880 881 typedef PODIntervalTree<float, SweepData*> SweepTree; 882 typedef SweepTree::IntervalType SweepInterval; 883 884 // The entry / exit events which occur at the minimum and maximum x 885 // coordinates of the control point triangles' bounding boxes. 886 // 887 // Note that this class requires its copy constructor and assignment 888 // operator since it needs to be stored in a Vector. 889 class SweepEvent { 890 public: 891 SweepEvent() 892 : m_x(0) 893 , m_entry(false) 894 , m_interval(0, 0, 0) 895 { 896 } 897 898 // Initializes the SweepEvent. 899 void setup(float x, bool entry, SweepInterval interval) 900 { 901 m_x = x; 902 m_entry = entry; 903 m_interval = interval; 904 } 905 906 float x() const { return m_x; } 907 bool entry() const { return m_entry; } 908 const SweepInterval& interval() const { return m_interval; } 909 910 bool operator<(const SweepEvent& other) const 911 { 912 return m_x < other.m_x; 913 } 914 915 private: 916 float m_x; 917 bool m_entry; 918 SweepInterval m_interval; 919 }; 920 921 bool trianglesOverlap(LoopBlinnLocalTriangulator::Triangle* t0, 922 LoopBlinnLocalTriangulator::Triangle* t1) 923 { 924 return trianglesOverlap(t0->getVertex(0)->xyCoordinates(), 925 t0->getVertex(1)->xyCoordinates(), 926 t0->getVertex(2)->xyCoordinates(), 927 t1->getVertex(0)->xyCoordinates(), 928 t1->getVertex(1)->xyCoordinates(), 929 t1->getVertex(2)->xyCoordinates()); 930 } 931 932 } // anonymous namespace 933 934 void LoopBlinnPathProcessor::subdivideCurves() 935 { 936 // We need to determine all overlaps of all control point triangles 937 // (from different segments, not the same segment) and, if any 938 // exist, subdivide the associated curves. 939 // 940 // The plane-sweep algorithm determines all overlaps of a set of 941 // rectangles in the 2D plane. Our problem maps very well to this 942 // algorithm and significantly reduces the complexity compared to a 943 // naive implementation. 944 // 945 // Each bounding box of a control point triangle is converted into 946 // an "entry" event at its smallest X coordinate and an "exit" event 947 // at its largest X coordinate. Each event has an associated 948 // one-dimensional interval representing the Y span of the bounding 949 // box. We sort these events by increasing X coordinate. We then 950 // iterate through them. For each entry event we add the interval to 951 // a side interval tree, and query this tree for overlapping 952 // intervals. Any overlapping interval corresponds to an overlapping 953 // bounding box. For each exit event we remove the associated 954 // interval from the interval tree. 955 956 Vector<Segment*> curSegments; 957 Vector<Segment*> nextSegments; 958 959 // Start things off by considering all of the segments 960 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 961 Contour* cur = *iter; 962 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 963 if (seg->kind() == Segment::Cubic) { 964 seg->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0); 965 curSegments.append(seg); 966 } 967 } 968 } 969 970 // Subdivide curves at most this many times 971 const int MaxIterations = 5; 972 Vector<SweepInterval> overlaps; 973 974 for (int currentIteration = 0; currentIteration < MaxIterations; ++currentIteration) { 975 if (!curSegments.size()) 976 // Done 977 break; 978 979 Vector<SweepEvent> events; 980 SweepTree tree(m_arena); 981 for (Vector<Segment*>::iterator iter = curSegments.begin(); iter != curSegments.end(); ++iter) { 982 Segment* seg = *iter; 983 ASSERT(seg->kind() == Segment::Cubic); 984 for (int i = 0; i < seg->numberOfTriangles(); i++) { 985 LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i); 986 FloatRect boundingBox; 987 boundingBox.fitToPoints(triangle->getVertex(0)->xyCoordinates(), 988 triangle->getVertex(1)->xyCoordinates(), 989 triangle->getVertex(2)->xyCoordinates()); 990 // Ignore zero-width triangles to avoid issues with 991 // coincident entry and exit events for the same triangle 992 if (boundingBox.maxX() > boundingBox.x()) { 993 SweepData* data = m_arena->allocateObject<SweepData>(); 994 data->triangle = triangle; 995 data->segment = seg; 996 SweepInterval interval = tree.createInterval(boundingBox.y(), boundingBox.maxY(), data); 997 // Add entry and exit events 998 SweepEvent event; 999 event.setup(boundingBox.x(), true, interval); 1000 events.append(event); 1001 event.setup(boundingBox.maxX(), false, interval); 1002 events.append(event); 1003 } 1004 } 1005 } 1006 1007 // Sort events by increasing X coordinate 1008 std::sort(events.begin(), events.end()); 1009 #ifndef NDEBUG 1010 for (size_t ii = 1; ii < events.size(); ++ii) 1011 ASSERT(events[ii - 1].x() <= events[ii].x()); 1012 #endif 1013 1014 // Now iterate through the events 1015 for (Vector<SweepEvent>::iterator iter = events.begin(); iter != events.end(); ++iter) { 1016 SweepEvent event = *iter; 1017 if (event.entry()) { 1018 // See whether the associated segment has been subdivided yet 1019 if (!event.interval().data()->segment->markedForSubdivision()) { 1020 // Query the tree 1021 overlaps.clear(); 1022 tree.allOverlaps(event.interval(), overlaps); 1023 // Now see exactly which triangles overlap this one 1024 for (Vector<SweepInterval>::iterator iter = overlaps.begin(); iter != overlaps.end(); ++iter) { 1025 SweepInterval overlap = *iter; 1026 // Only pay attention to overlaps from a different Segment 1027 if (event.interval().data()->segment != overlap.data()->segment) { 1028 // See whether the triangles actually overlap 1029 if (trianglesOverlap(event.interval().data()->triangle, 1030 overlap.data()->triangle)) { 1031 // Actually subdivide the segments. 1032 // Each one might already have been subdivided. 1033 Segment* seg = event.interval().data()->segment; 1034 conditionallySubdivide(seg, nextSegments); 1035 seg = overlap.data()->segment; 1036 conditionallySubdivide(seg, nextSegments); 1037 } 1038 } 1039 } 1040 } 1041 // Add this interval into the tree 1042 tree.add(event.interval()); 1043 } else { 1044 // Remove this interval from the tree 1045 tree.remove(event.interval()); 1046 } 1047 } 1048 1049 curSegments.swap(nextSegments); 1050 nextSegments.clear(); 1051 } 1052 } 1053 1054 void LoopBlinnPathProcessor::conditionallySubdivide(Segment* seg, Vector<Segment*>& nextSegments) 1055 { 1056 if (!seg->markedForSubdivision()) { 1057 seg->setMarkedForSubdivision(true); 1058 Segment* next = seg->contour()->subdivide(seg); 1059 // Triangulate the newly subdivided segments. 1060 next->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0); 1061 next->next()->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0); 1062 // Add them for the next iteration. 1063 nextSegments.append(next); 1064 nextSegments.append(next->next()); 1065 } 1066 } 1067 1068 #ifndef NDEBUG 1069 void LoopBlinnPathProcessor::subdivideCurvesSlow() 1070 { 1071 // Alternate, significantly slower algorithm for curve subdivision 1072 // for use in debugging. 1073 Vector<Segment*> curSegments; 1074 Vector<Segment*> nextSegments; 1075 1076 // Start things off by considering all of the segments 1077 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 1078 Contour* cur = *iter; 1079 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 1080 if (seg->kind() == Segment::Cubic) { 1081 seg->triangulate(LoopBlinnLocalTriangulator::DontComputeInsideEdges, 0); 1082 curSegments.append(seg); 1083 } 1084 } 1085 } 1086 1087 // Subdivide curves at most this many times 1088 const int MaxIterations = 5; 1089 1090 for (int currentIteration = 0; currentIteration < MaxIterations; ++currentIteration) { 1091 if (!curSegments.size()) 1092 // Done 1093 break; 1094 1095 for (Vector<Segment*>::iterator iter = curSegments.begin(); iter != curSegments.end(); ++iter) { 1096 Segment* seg = *iter; 1097 ASSERT(seg->kind() == Segment::Cubic); 1098 for (Vector<Segment*>::iterator iter2 = curSegments.begin(); 1099 iter2 != curSegments.end(); 1100 iter2++) { 1101 Segment* seg2 = *iter2; 1102 ASSERT(seg2->kind() == Segment::Cubic); 1103 if (seg != seg2) { 1104 for (int i = 0; i < seg->numberOfTriangles(); i++) { 1105 LoopBlinnLocalTriangulator::Triangle* triangle = seg->getTriangle(i); 1106 for (int j = 0; j < seg2->numberOfTriangles(); j++) { 1107 LoopBlinnLocalTriangulator::Triangle* triangle2 = seg2->getTriangle(j); 1108 if (trianglesOverlap(triangle, triangle2)) { 1109 conditionallySubdivide(seg, nextSegments); 1110 conditionallySubdivide(seg2, nextSegments); 1111 } 1112 } 1113 } 1114 } 1115 } 1116 } 1117 1118 curSegments.swap(nextSegments); 1119 nextSegments.clear(); 1120 } 1121 } 1122 #endif 1123 1124 namespace { 1125 1126 //---------------------------------------------------------------------- 1127 // Structures and callbacks for tessellation of the interior region of 1128 // the contours. 1129 1130 // The user data for the GLU tessellator. 1131 struct TessellationState { 1132 TessellationState(LoopBlinnPathCache& inputCache) 1133 : cache(inputCache) { } 1134 1135 LoopBlinnPathCache& cache; 1136 Vector<void*> allocatedPointers; 1137 }; 1138 1139 static void vertexCallback(void* vertexData, void* data) 1140 { 1141 TessellationState* state = static_cast<TessellationState*>(data); 1142 GLdouble* location = static_cast<GLdouble*>(vertexData); 1143 state->cache.addInteriorVertex(static_cast<float>(location[0]), 1144 static_cast<float>(location[1])); 1145 } 1146 1147 static void combineCallback(GLdouble coords[3], void* vertexData[4], 1148 GLfloat weight[4], void** outData, 1149 void* polygonData) 1150 { 1151 UNUSED_PARAM(vertexData); 1152 UNUSED_PARAM(weight); 1153 TessellationState* state = static_cast<TessellationState*>(polygonData); 1154 GLdouble* outVertex = static_cast<GLdouble*>(fastMalloc(3 * sizeof(GLdouble))); 1155 state->allocatedPointers.append(outVertex); 1156 outVertex[0] = coords[0]; 1157 outVertex[1] = coords[1]; 1158 outVertex[2] = coords[2]; 1159 *outData = outVertex; 1160 } 1161 1162 static void edgeFlagCallback(GLboolean) 1163 { 1164 // No-op just to prevent triangle strips and fans from being passed to us. 1165 // See the OpenGL Programming Guide, Chapter 11, "Tessellators and Quadrics". 1166 } 1167 1168 } // anonymous namespace 1169 1170 void LoopBlinnPathProcessor::tessellateInterior(LoopBlinnPathCache& cache) 1171 { 1172 // Because the GLU tessellator requires its input in 1173 // double-precision format, we need to make a separate copy of the 1174 // data. 1175 Vector<GLdouble> vertexData; 1176 Vector<size_t> contourEndings; 1177 // For avoiding adding coincident vertices. 1178 float curX = 0, curY = 0; 1179 for (Vector<Contour*>::iterator iter = m_contours.begin(); iter != m_contours.end(); ++iter) { 1180 Contour* cur = *iter; 1181 bool first = true; 1182 for (Segment* seg = cur->begin(); seg != cur->end(); seg = seg->next()) { 1183 int numberOfInteriorVertices = seg->numberOfInteriorVertices(); 1184 for (int i = 0; i < numberOfInteriorVertices - 1; i++) { 1185 FloatPoint point = seg->getInteriorVertex(i); 1186 if (first) { 1187 first = false; 1188 vertexData.append(point.x()); 1189 vertexData.append(point.y()); 1190 vertexData.append(0); 1191 curX = point.x(); 1192 curY = point.y(); 1193 } else if (point.x() != curX || point.y() != curY) { 1194 vertexData.append(point.x()); 1195 vertexData.append(point.y()); 1196 vertexData.append(0); 1197 curX = point.x(); 1198 curY = point.y(); 1199 } 1200 } 1201 } 1202 contourEndings.append(vertexData.size()); 1203 } 1204 // Now that we have all of the vertex data in a stable location in 1205 // memory, call the tessellator. 1206 GLUtesselator* tess = internal_gluNewTess(); 1207 TessellationState state(cache); 1208 internal_gluTessCallback(tess, GLU_TESS_VERTEX_DATA, 1209 reinterpret_cast<GLvoid (*)()>(vertexCallback)); 1210 internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA, 1211 reinterpret_cast<GLvoid (*)()>(combineCallback)); 1212 internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG, 1213 reinterpret_cast<GLvoid (*)()>(edgeFlagCallback)); 1214 internal_gluTessBeginPolygon(tess, &state); 1215 internal_gluTessBeginContour(tess); 1216 GLdouble* base = vertexData.data(); 1217 int contourIndex = 0; 1218 for (size_t i = 0; i < vertexData.size(); i += 3) { 1219 if (i == contourEndings[contourIndex]) { 1220 internal_gluTessEndContour(tess); 1221 internal_gluTessBeginContour(tess); 1222 ++contourIndex; 1223 } 1224 internal_gluTessVertex(tess, &base[i], &base[i]); 1225 } 1226 internal_gluTessEndContour(tess); 1227 internal_gluTessEndPolygon(tess); 1228 for (size_t i = 0; i < state.allocatedPointers.size(); i++) 1229 fastFree(state.allocatedPointers[i]); 1230 internal_gluDeleteTess(tess); 1231 } 1232 1233 } // namespace WebCore 1234