Home | History | Annotate | Download | only in pathops
      1 /*
      2 * Copyright 2013 Google Inc.
      3 *
      4 * Use of this source code is governed by a BSD-style license that can be
      5 * found in the LICENSE file.
      6 */
      7 #include "SkOpContour.h"
      8 #include "SkPathWriter.h"
      9 #include "SkReduceOrder.h"
     10 #include "SkTSort.h"
     11 
     12 void SkOpContour::toPath(SkPathWriter* path) const {
     13     if (!this->count()) {
     14         return;
     15     }
     16     const SkOpSegment* segment = &fHead;
     17     do {
     18         SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
     19     } while ((segment = segment->next()));
     20     path->finishContour();
     21     path->assemble();
     22 }
     23 
     24 void SkOpContour::toReversePath(SkPathWriter* path) const {
     25     const SkOpSegment* segment = fTail;
     26     do {
     27         SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
     28     } while ((segment = segment->prev()));
     29     path->finishContour();
     30     path->assemble();
     31 }
     32 
     33 SkOpSpan* SkOpContour::undoneSpan() {
     34     SkOpSegment* testSegment = &fHead;
     35     do {
     36         if (testSegment->done()) {
     37             continue;
     38         }
     39         return testSegment->undoneSpan();
     40     } while ((testSegment = testSegment->next()));
     41     fDone = true;
     42     return nullptr;
     43 }
     44 
     45 void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) {
     46     this->flush();
     47     fContour->addConic(pts, weight);
     48 }
     49 
     50 void SkOpContourBuilder::addCubic(SkPoint pts[4]) {
     51     this->flush();
     52     fContour->addCubic(pts);
     53 }
     54 
     55 void SkOpContourBuilder::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) {
     56     if (SkPath::kLine_Verb == verb) {
     57         this->addLine(pts);
     58         return;
     59     }
     60     SkArenaAlloc* allocator = fContour->globalState()->allocator();
     61     switch (verb) {
     62         case SkPath::kQuad_Verb: {
     63             SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
     64             memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
     65             this->addQuad(ptStorage);
     66         } break;
     67         case SkPath::kConic_Verb: {
     68             SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
     69             memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
     70             this->addConic(ptStorage, weight);
     71         } break;
     72         case SkPath::kCubic_Verb: {
     73             SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(4);
     74             memcpy(ptStorage, pts, sizeof(SkPoint) * 4);
     75             this->addCubic(ptStorage);
     76         } break;
     77         default:
     78             SkASSERT(0);
     79     }
     80 }
     81 
     82 void SkOpContourBuilder::addLine(const SkPoint pts[2]) {
     83     // if the previous line added is the exact opposite, eliminate both
     84     if (fLastIsLine) {
     85         if (fLastLine[0] == pts[1] && fLastLine[1] == pts[0]) {
     86             fLastIsLine = false;
     87             return;
     88         } else {
     89             flush();
     90         }
     91     }
     92     memcpy(fLastLine, pts, sizeof(fLastLine));
     93     fLastIsLine = true;
     94 }
     95 
     96 void SkOpContourBuilder::addQuad(SkPoint pts[3]) {
     97     this->flush();
     98     fContour->addQuad(pts);
     99 }
    100 
    101 void SkOpContourBuilder::flush() {
    102     if (!fLastIsLine)
    103         return;
    104     SkArenaAlloc* allocator = fContour->globalState()->allocator();
    105     SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(2);
    106     memcpy(ptStorage, fLastLine, sizeof(fLastLine));
    107     (void) fContour->addLine(ptStorage);
    108     fLastIsLine = false;
    109 }
    110