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
56namespace WebCore {
57
58using LoopBlinnMathUtils::XRay;
59using LoopBlinnMathUtils::chopCubicAt;
60using LoopBlinnMathUtils::numXRayCrossingsForCubic;
61using LoopBlinnMathUtils::trianglesOverlap;
62using LoopBlinnMathUtils::xRayCrossesLine;
63using LoopBlinnPathProcessorImplementation::Contour;
64using LoopBlinnPathProcessorImplementation::Segment;
65
66namespace {
67
68#ifndef NDEBUG
69String 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
85struct SweepData;
86
87} // anonymous namespace
88
89namespace LoopBlinnPathProcessorImplementation {
90class Segment;
91}
92
93#ifndef NDEBUG
94// Routines needed to print the types of IntervalNodes we instantiate
95// in this file.
96template <>
97struct ValueToString<float> {
98    static String string(const float& value)
99    {
100        return String::number(value);
101    }
102};
103
104template <>
105struct ValueToString<SweepData*> {
106    static String string(SweepData* const& value)
107    {
108        return String::format("0x%p", value);
109    }
110};
111
112template <>
113struct ValueToString<LoopBlinnPathProcessorImplementation::Segment*> {
114    static String string(LoopBlinnPathProcessorImplementation::Segment* const& value)
115    {
116        return String::format("0x%p", value);
117    }
118};
119#endif
120
121namespace 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.
131class Segment {
132    WTF_MAKE_NONCOPYABLE(Segment);
133public:
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.
360class Contour {
361    WTF_MAKE_NONCOPYABLE(Contour);
362public:
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
464private:
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.
489void 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
520LoopBlinnPathProcessor::LoopBlinnPathProcessor()
521    : m_arena(PODArena::create())
522#ifndef NDEBUG
523    , m_verboseLogging(false)
524#endif
525{
526}
527
528LoopBlinnPathProcessor::LoopBlinnPathProcessor(PassRefPtr<PODArena> arena)
529    : m_arena(arena)
530#ifndef NDEBUG
531    , m_verboseLogging(false)
532#endif
533{
534}
535
536LoopBlinnPathProcessor::~LoopBlinnPathProcessor()
537{
538}
539
540void 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
613void 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
713Vector<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
731void 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
828void 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
860namespace {
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.
868struct 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
881typedef PODIntervalTree<float, SweepData*> SweepTree;
882typedef 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.
889class SweepEvent {
890public:
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
915private:
916    float m_x;
917    bool m_entry;
918    SweepInterval m_interval;
919};
920
921bool 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
934void 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
1054void 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
1069void 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
1124namespace {
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.
1131struct TessellationState {
1132    TessellationState(LoopBlinnPathCache& inputCache)
1133        : cache(inputCache) { }
1134
1135    LoopBlinnPathCache& cache;
1136    Vector<void*> allocatedPointers;
1137};
1138
1139static 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
1147static 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
1162static 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
1170void 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