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 "SkDrawGradient.h"
11#include "SkAnimateMaker.h"
12#include "SkAnimatorScript.h"
13#include "SkGradientShader.h"
14
15#if SK_USE_CONDENSED_INFO == 0
16
17const SkMemberInfo SkDrawGradient::fInfo[] = {
18    SK_MEMBER_INHERITED,
19    SK_MEMBER_ARRAY(offsets, Float),
20    SK_MEMBER(unitMapper, String)
21};
22
23#endif
24
25DEFINE_GET_MEMBER(SkDrawGradient);
26
27SkDrawGradient::SkDrawGradient() {
28}
29
30SkDrawGradient::~SkDrawGradient() {
31    for (int index = 0; index < fDrawColors.count(); index++)
32        delete fDrawColors[index];
33}
34
35bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) {
36    SkASSERT(child);
37    if (child->isColor()) {
38        SkDrawColor* color = (SkDrawColor*) child;
39        *fDrawColors.append() = color;
40        return true;
41    }
42    return false;
43}
44
45int SkDrawGradient::addPrelude() {
46    int count = fDrawColors.count();
47    fColors.setCount(count);
48    for (int index = 0; index < count; index++)
49        fColors[index] = fDrawColors[index]->color;
50    return count;
51}
52
53#ifdef SK_DUMP_ENABLED
54void SkDrawGradient::dumpRest(SkAnimateMaker* maker) {
55    dumpAttrs(maker);
56    //can a gradient have no colors?
57    bool closedYet = false;
58    SkDisplayList::fIndent += 4;
59    for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
60        if (closedYet == false) {
61            SkDebugf(">\n");
62            closedYet = true;
63        }
64        SkDrawColor* color = *ptr;
65        color->dump(maker);
66    }
67    SkDisplayList::fIndent -= 4;
68    dumpChildren(maker, closedYet); //dumps the matrix if it has one
69}
70#endif
71
72void SkDrawGradient::onEndElement(SkAnimateMaker& maker) {
73    if (offsets.count() != 0) {
74        if (offsets.count() != fDrawColors.count()) {
75            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
76            return;
77        }
78        if (offsets[0] != 0) {
79            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
80            return;
81        }
82        if (offsets[offsets.count()-1] != SK_Scalar1) {
83            maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
84            return;
85        }
86        for (int i = 1; i < offsets.count(); i++) {
87            if (offsets[i] <= offsets[i-1]) {
88                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
89                return;
90            }
91            if (offsets[i] > SK_Scalar1) {
92                maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
93                return;
94            }
95        }
96    }
97    INHERITED::onEndElement(maker);
98}
99
100#if SK_USE_CONDENSED_INFO == 0
101
102const SkMemberInfo SkDrawLinearGradient::fInfo[] = {
103    SK_MEMBER_INHERITED,
104    SK_MEMBER_ARRAY(points, Float),
105};
106
107#endif
108
109DEFINE_GET_MEMBER(SkDrawLinearGradient);
110
111SkDrawLinearGradient::SkDrawLinearGradient() {
112}
113
114void SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker)
115{
116    if (points.count() != 4)
117        maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
118    INHERITED::onEndElement(maker);
119}
120
121#ifdef SK_DUMP_ENABLED
122void SkDrawLinearGradient::dump(SkAnimateMaker* maker) {
123    dumpBase(maker);
124    dumpRest(maker);
125    }
126#endif
127
128SkShader* SkDrawLinearGradient::getShader() {
129    if (addPrelude() == 0 || points.count() != 4)
130        return NULL;
131    SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
132        fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
133        0, getMatrix());
134    SkAutoTDelete<SkShader> autoDel(shader);
135    (void)autoDel.detach();
136    return shader;
137}
138
139
140#if SK_USE_CONDENSED_INFO == 0
141
142const SkMemberInfo SkDrawRadialGradient::fInfo[] = {
143    SK_MEMBER_INHERITED,
144    SK_MEMBER(center, Point),
145    SK_MEMBER(radius, Float)
146};
147
148#endif
149
150DEFINE_GET_MEMBER(SkDrawRadialGradient);
151
152SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) {
153    center.set(0, 0);
154}
155
156#ifdef SK_DUMP_ENABLED
157void SkDrawRadialGradient::dump(SkAnimateMaker* maker) {
158    dumpBase(maker);
159    dumpRest(maker);
160}
161#endif
162
163SkShader* SkDrawRadialGradient::getShader() {
164    if (addPrelude() == 0)
165        return NULL;
166    SkShader* shader = SkGradientShader::CreateRadial(center,
167        radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
168        0, getMatrix());
169    SkAutoTDelete<SkShader> autoDel(shader);
170    (void)autoDel.detach();
171    return shader;
172}
173