Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkPathEffect.h"
     11 #include "SkPath.h"
     12 #include "SkBuffer.h"
     13 
     14 ///////////////////////////////////////////////////////////////////////////////
     15 
     16 SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)
     17         : fPE0(pe0), fPE1(pe1) {
     18     SkASSERT(pe0);
     19     SkASSERT(pe1);
     20     fPE0->ref();
     21     fPE1->ref();
     22 }
     23 
     24 SkPairPathEffect::~SkPairPathEffect() {
     25     SkSafeUnref(fPE0);
     26     SkSafeUnref(fPE1);
     27 }
     28 
     29 /*
     30     Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data]
     31 */
     32 void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
     33     buffer.writeFlattenable(fPE0);
     34     buffer.writeFlattenable(fPE1);
     35 }
     36 
     37 SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
     38     fPE0 = (SkPathEffect*)buffer.readFlattenable();
     39     fPE1 = (SkPathEffect*)buffer.readFlattenable();
     40     // either of these may fail, so we have to check for nulls later on
     41 }
     42 
     43 ///////////////////////////////////////////////////////////////////////////////
     44 
     45 bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src,
     46                                      SkScalar* width) {
     47     // we may have failed to unflatten these, so we have to check
     48     if (!fPE0 || !fPE1) {
     49         return false;
     50     }
     51 
     52     SkPath          tmp;
     53     const SkPath*   ptr = &src;
     54 
     55     if (fPE1->filterPath(&tmp, src, width)) {
     56         ptr = &tmp;
     57     }
     58     return fPE0->filterPath(dst, *ptr, width);
     59 }
     60 
     61 ///////////////////////////////////////////////////////////////////////////////
     62 
     63 bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
     64                                  SkScalar* width) {
     65     // use bit-or so that we always call both, even if the first one succeeds
     66     return  fPE0->filterPath(dst, src, width) | fPE1->filterPath(dst, src, width);
     67 }
     68 
     69 ///////////////////////////////////////////////////////////////////////////////
     70 
     71 #include "SkStroke.h"
     72 
     73 SkStrokePathEffect::SkStrokePathEffect(const SkPaint& paint)
     74     : fWidth(paint.getStrokeWidth()), fMiter(paint.getStrokeMiter()),
     75       fStyle(SkToU8(paint.getStyle())), fJoin(SkToU8(paint.getStrokeJoin())),
     76       fCap(SkToU8(paint.getStrokeCap())) {
     77 }
     78 
     79 SkStrokePathEffect::SkStrokePathEffect(SkScalar width, SkPaint::Style style,
     80                            SkPaint::Join join, SkPaint::Cap cap, SkScalar miter)
     81         : fWidth(width), fMiter(miter), fStyle(SkToU8(style)),
     82           fJoin(SkToU8(join)), fCap(SkToU8(cap)) {
     83     if (miter < 0) {  // signal they want the default
     84         fMiter = SkIntToScalar(4);
     85     }
     86 }
     87 
     88 bool SkStrokePathEffect::filterPath(SkPath* dst, const SkPath& src,
     89                                     SkScalar* width) {
     90     if (fWidth < 0 || fStyle == SkPaint::kFill_Style) {
     91         return false;
     92     }
     93 
     94     if (fStyle == SkPaint::kStroke_Style && fWidth == 0) {  // hairline
     95         *width = 0;
     96         return true;
     97     }
     98 
     99     SkStroke    stroke;
    100 
    101     stroke.setWidth(fWidth);
    102     stroke.setMiterLimit(fMiter);
    103     stroke.setJoin((SkPaint::Join)fJoin);
    104     stroke.setCap((SkPaint::Cap)fCap);
    105     stroke.setDoFill(fStyle == SkPaint::kStrokeAndFill_Style);
    106 
    107     stroke.strokePath(src, dst);
    108     return true;
    109 }
    110 
    111 SkFlattenable::Factory SkStrokePathEffect::getFactory() {
    112     return CreateProc;
    113 }
    114 
    115 SkFlattenable* SkStrokePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
    116     return SkNEW_ARGS(SkStrokePathEffect, (buffer));
    117 }
    118 
    119 void SkStrokePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
    120     buffer.writeScalar(fWidth);
    121     buffer.writeScalar(fMiter);
    122     buffer.write8(fStyle);
    123     buffer.write8(fJoin);
    124     buffer.write8(fCap);
    125 }
    126 
    127 SkStrokePathEffect::SkStrokePathEffect(SkFlattenableReadBuffer& buffer) {
    128     fWidth = buffer.readScalar();
    129     fMiter = buffer.readScalar();
    130     fStyle = buffer.readU8();
    131     fJoin = buffer.readU8();
    132     fCap = buffer.readU8();
    133 }
    134 
    135 ///////////////////////////////////////////////////////////////////////////////
    136 
    137 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkPathEffect)
    138     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposePathEffect)
    139     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStrokePathEffect)
    140     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
    141 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
    142 
    143