1/*
2 * Copyright 2006 The Android Open Source Project
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
8#include "SkDrawPaint.h"
9#include "SkAnimateMaker.h"
10#include "SkDrawColor.h"
11#include "SkDrawShader.h"
12#include "SkMaskFilter.h"
13#include "SkPaintPart.h"
14#include "SkPathEffect.h"
15
16enum SkPaint_Functions {
17    SK_FUNCTION(measureText)
18};
19
20enum SkPaint_Properties {
21    SK_PROPERTY(ascent),
22    SK_PROPERTY(descent)
23};
24
25// !!! in the future, this could be compiled by build-condensed-info into an array of parameters
26// with a lookup table to find the first parameter -- for now, it is iteratively searched through
27const SkFunctionParamType SkDrawPaint::fFunctionParameters[] = {
28    (SkFunctionParamType) SkType_String,
29    (SkFunctionParamType) 0 // terminator for parameter list (there may be multiple parameter lists)
30};
31
32
33#if SK_USE_CONDENSED_INFO == 0
34
35const SkMemberInfo SkDrawPaint::fInfo[] = {
36    SK_MEMBER(antiAlias, Boolean),
37    SK_MEMBER_PROPERTY(ascent, Float),
38    SK_MEMBER(color, Color),
39    SK_MEMBER_PROPERTY(descent, Float),
40    SK_MEMBER(fakeBold, Boolean),
41    SK_MEMBER(filterBitmap, Boolean),
42    SK_MEMBER(linearText, Boolean),
43    SK_MEMBER(maskFilter, MaskFilter),
44    SK_MEMBER_FUNCTION(measureText, Float),
45    SK_MEMBER(pathEffect, PathEffect),
46    SK_MEMBER(shader, Shader),
47    SK_MEMBER(strikeThru, Boolean),
48    SK_MEMBER(stroke, Boolean),
49    SK_MEMBER(strokeCap, Cap),
50    SK_MEMBER(strokeJoin, Join),
51    SK_MEMBER(strokeMiter, Float),
52    SK_MEMBER(strokeWidth, Float),
53    SK_MEMBER(style, Style),
54    SK_MEMBER(textAlign, Align),
55    SK_MEMBER(textScaleX, Float),
56    SK_MEMBER(textSize, Float),
57    SK_MEMBER(textSkewX, Float),
58    SK_MEMBER(typeface, Typeface),
59    SK_MEMBER(underline, Boolean),
60    SK_MEMBER(xfermode, Xfermode)
61};
62
63#endif
64
65DEFINE_GET_MEMBER(SkDrawPaint);
66
67SkDrawPaint::SkDrawPaint() : antiAlias(-1), color(nullptr), fakeBold(-1), filterBitmap(-1),
68    linearText(-1), maskFilter((SkDrawMaskFilter*) -1), pathEffect((SkDrawPathEffect*) -1),
69    shader((SkDrawShader*) -1), strikeThru(-1), stroke(-1),
70    strokeCap((SkPaint::Cap) -1), strokeJoin((SkPaint::Join) -1), strokeMiter(SK_ScalarNaN),
71    strokeWidth(SK_ScalarNaN), style((SkPaint::Style) -1),
72    textAlign((SkPaint::Align) -1), textScaleX(SK_ScalarNaN), textSize(SK_ScalarNaN),
73    textSkewX(SK_ScalarNaN), typeface((SkDrawTypeface*) -1),
74    underline(-1), xfermode((SkXfermode::Mode) -1), fOwnsColor(false), fOwnsMaskFilter(false),
75    fOwnsPathEffect(false), fOwnsShader(false), fOwnsTypeface(false) {
76}
77
78SkDrawPaint::~SkDrawPaint() {
79    if (fOwnsColor)
80        delete color;
81    if (fOwnsMaskFilter)
82        delete maskFilter;
83    if (fOwnsPathEffect)
84        delete pathEffect;
85    if (fOwnsShader)
86        delete shader;
87    if (fOwnsTypeface)
88        delete typeface;
89}
90
91bool SkDrawPaint::add(SkAnimateMaker* maker, SkDisplayable* child) {
92    SkASSERT(child && child->isPaintPart());
93    SkPaintPart* part = (SkPaintPart*) child;
94    if (part->add() && maker)
95        maker->setErrorCode(SkDisplayXMLParserError::kErrorAddingToPaint);
96    return true;
97}
98
99SkDisplayable* SkDrawPaint::deepCopy(SkAnimateMaker* maker) {
100    SkDrawColor* tempColor = color;
101    color = nullptr;
102    SkDrawPaint* copy = (SkDrawPaint*) INHERITED::deepCopy(maker);
103    color = tempColor;
104    tempColor = (SkDrawColor*) color->deepCopy(maker);
105    tempColor->setParent(copy);
106    tempColor->add();
107    copy->fOwnsColor = true;
108    return copy;
109}
110
111bool SkDrawPaint::draw(SkAnimateMaker& maker) {
112    SkPaint* paint = maker.fPaint;
113    setupPaint(paint);
114    return false;
115}
116
117#ifdef SK_DUMP_ENABLED
118void SkDrawPaint::dump(SkAnimateMaker* maker) {
119    dumpBase(maker);
120    dumpAttrs(maker);
121    bool closedYet = false;
122    SkDisplayList::fIndent +=4;
123    //should i say if (maskFilter && ...?
124    if (maskFilter != (SkDrawMaskFilter*)-1) {
125        SkDebugf(">\n");
126        maskFilter->dump(maker);
127        closedYet = true;
128    }
129    if (pathEffect != (SkDrawPathEffect*) -1) {
130        if (closedYet == false) {
131            SkDebugf(">\n");
132            closedYet = true;
133        }
134        pathEffect->dump(maker);
135    }
136    if (fOwnsTypeface) {
137        if (closedYet == false) {
138            SkDebugf(">\n");
139            closedYet = true;
140        }
141        typeface->dump(maker);
142    }
143    SkDisplayList::fIndent -= 4;
144    dumpChildren(maker, closedYet);
145}
146#endif
147
148void SkDrawPaint::executeFunction(SkDisplayable* target, int index,
149        SkTDArray<SkScriptValue>& parameters, SkDisplayTypes type,
150        SkScriptValue* scriptValue) {
151        if (scriptValue == nullptr)
152            return;
153    SkASSERT(target == this);
154    switch (index) {
155        case SK_FUNCTION(measureText): {
156            SkASSERT(parameters.count() == 1);
157            SkASSERT(type == SkType_Float);
158            SkPaint paint;
159            setupPaint(&paint);
160            scriptValue->fType = SkType_Float;
161            SkASSERT(parameters[0].fType == SkType_String);
162            scriptValue->fOperand.fScalar = paint.measureText(parameters[0].fOperand.fString->c_str(),
163                parameters[0].fOperand.fString->size());
164//          SkDebugf("measureText: %s = %g\n", parameters[0].fOperand.fString->c_str(),
165//              scriptValue->fOperand.fScalar / 65536.0f);
166            } break;
167        default:
168            SkASSERT(0);
169    }
170}
171
172const SkFunctionParamType* SkDrawPaint::getFunctionsParameters() {
173    return fFunctionParameters;
174}
175
176bool SkDrawPaint::getProperty(int index, SkScriptValue* value) const {
177    SkPaint::FontMetrics    metrics;
178    SkPaint paint;
179    setupPaint(&paint);
180    paint.getFontMetrics(&metrics);
181    switch (index) {
182        case SK_PROPERTY(ascent):
183            value->fOperand.fScalar = metrics.fAscent;
184            break;
185        case SK_PROPERTY(descent):
186            value->fOperand.fScalar = metrics.fDescent;
187            break;
188        // should consider returning fLeading as well (or roll it into ascent/descent somehow
189        default:
190            SkASSERT(0);
191            return false;
192    }
193    value->fType = SkType_Float;
194    return true;
195}
196
197bool SkDrawPaint::resolveIDs(SkAnimateMaker& maker, SkDisplayable* origDisp, SkApply* ) {
198    SkASSERT(origDisp->isPaint());
199    SkDrawPaint* original = (SkDrawPaint*) origDisp;
200    if (fOwnsColor && maker.resolveID(color, original->color) == false)
201        return true;
202    if (fOwnsMaskFilter && maker.resolveID(maskFilter, original->maskFilter) == false)
203        return true;
204    if (fOwnsPathEffect && maker.resolveID(pathEffect, original->pathEffect) == false)
205        return true;
206    if (fOwnsShader && maker.resolveID(shader, original->shader) == false)
207        return true;
208    if (fOwnsTypeface && maker.resolveID(typeface, original->typeface) == false)
209        return true;
210    return false; // succeeded
211}
212
213void SkDrawPaint::setupPaint(SkPaint* paint) const {
214    if (antiAlias != -1)
215        paint->setAntiAlias(SkToBool(antiAlias));
216    if (color != nullptr)
217        paint->setColor(color->getColor());
218    if (fakeBold != -1)
219        paint->setFakeBoldText(SkToBool(fakeBold));
220    if (filterBitmap != -1)
221        paint->setFilterQuality(filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality);
222    //  stroke is legacy; style setting if present overrides stroke
223    if (stroke != -1)
224        paint->setStyle(SkToBool(stroke) ? SkPaint::kStroke_Style : SkPaint::kFill_Style);
225    if (style != -1)
226        paint->setStyle((SkPaint::Style) style);
227    if (linearText != -1)
228        paint->setLinearText(SkToBool(linearText));
229    if (maskFilter == nullptr)
230        paint->setMaskFilter(nullptr);
231    else if (maskFilter != (SkDrawMaskFilter*) -1)
232        SkSafeUnref(paint->setMaskFilter(maskFilter->getMaskFilter()));
233    if (pathEffect == nullptr)
234        paint->setPathEffect(nullptr);
235    else if (pathEffect != (SkDrawPathEffect*) -1)
236        SkSafeUnref(paint->setPathEffect(pathEffect->getPathEffect()));
237    if (shader == nullptr)
238        paint->setShader(nullptr);
239    else if (shader != (SkDrawShader*) -1)
240        SkSafeUnref(paint->setShader(shader->getShader()));
241    if (strikeThru != -1)
242        paint->setStrikeThruText(SkToBool(strikeThru));
243    if (strokeCap != -1)
244        paint->setStrokeCap((SkPaint::Cap) strokeCap);
245    if (strokeJoin != -1)
246        paint->setStrokeJoin((SkPaint::Join) strokeJoin);
247    if (SkScalarIsNaN(strokeMiter) == false)
248        paint->setStrokeMiter(strokeMiter);
249    if (SkScalarIsNaN(strokeWidth) == false)
250        paint->setStrokeWidth(strokeWidth);
251    if (textAlign != -1)
252        paint->setTextAlign((SkPaint::Align) textAlign);
253    if (SkScalarIsNaN(textScaleX) == false)
254        paint->setTextScaleX(textScaleX);
255    if (SkScalarIsNaN(textSize) == false)
256        paint->setTextSize(textSize);
257    if (SkScalarIsNaN(textSkewX) == false)
258        paint->setTextSkewX(textSkewX);
259    if (typeface == nullptr)
260        paint->setTypeface(nullptr);
261    else if (typeface != (SkDrawTypeface*) -1)
262        SkSafeUnref(paint->setTypeface(typeface->getTypeface()));
263    if (underline != -1)
264        paint->setUnderlineText(SkToBool(underline));
265    if (xfermode != -1)
266        paint->setXfermodeMode((SkXfermode::Mode) xfermode);
267}
268