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 
17 const SkMemberInfo SkDrawGradient::fInfo[] = {
18     SK_MEMBER_INHERITED,
19     SK_MEMBER_ARRAY(offsets, Float),
20     SK_MEMBER(unitMapper, String)
21 };
22 
23 #endif
24 
25 DEFINE_GET_MEMBER(SkDrawGradient);
26 
SkDrawGradient()27 SkDrawGradient::SkDrawGradient() {
28 }
29 
~SkDrawGradient()30 SkDrawGradient::~SkDrawGradient() {
31     for (int index = 0; index < fDrawColors.count(); index++)
32         delete fDrawColors[index];
33 }
34 
addChild(SkAnimateMaker &,SkDisplayable * child)35 bool 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 
addPrelude()45 int 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
dumpRest(SkAnimateMaker * maker)54 void 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 
onEndElement(SkAnimateMaker & maker)72 void 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 
102 const SkMemberInfo SkDrawLinearGradient::fInfo[] = {
103     SK_MEMBER_INHERITED,
104     SK_MEMBER_ARRAY(points, Float),
105 };
106 
107 #endif
108 
109 DEFINE_GET_MEMBER(SkDrawLinearGradient);
110 
SkDrawLinearGradient()111 SkDrawLinearGradient::SkDrawLinearGradient() {
112 }
113 
onEndElement(SkAnimateMaker & maker)114 void 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
dump(SkAnimateMaker * maker)122 void SkDrawLinearGradient::dump(SkAnimateMaker* maker) {
123     dumpBase(maker);
124     dumpRest(maker);
125     }
126 #endif
127 
getShader()128 SkShader* SkDrawLinearGradient::getShader() {
129     if (addPrelude() == 0 || points.count() != 4)
130         return nullptr;
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 
142 const SkMemberInfo SkDrawRadialGradient::fInfo[] = {
143     SK_MEMBER_INHERITED,
144     SK_MEMBER(center, Point),
145     SK_MEMBER(radius, Float)
146 };
147 
148 #endif
149 
150 DEFINE_GET_MEMBER(SkDrawRadialGradient);
151 
SkDrawRadialGradient()152 SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) {
153     center.set(0, 0);
154 }
155 
156 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)157 void SkDrawRadialGradient::dump(SkAnimateMaker* maker) {
158     dumpBase(maker);
159     dumpRest(maker);
160 }
161 #endif
162 
getShader()163 SkShader* SkDrawRadialGradient::getShader() {
164     if (addPrelude() == 0)
165         return nullptr;
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