• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/svg/SkSVGGradient.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkSVGGradient.h"
19 #include "SkSVGParser.h"
20 #include "SkSVGStop.h"
21 
SkSVGGradient()22 SkSVGGradient::SkSVGGradient() {
23 }
24 
getGradient()25 SkSVGElement* SkSVGGradient::getGradient() {
26     return this;
27 }
28 
isDef()29 bool SkSVGGradient::isDef() {
30     return true;
31 }
32 
isNotDef()33 bool SkSVGGradient::isNotDef() {
34     return false;
35 }
36 
translate(SkSVGParser & parser,bool defState)37 void SkSVGGradient::translate(SkSVGParser& parser, bool defState) {
38     INHERITED::translate(parser, defState);
39     // !!! no support for 'objectBoundingBox' yet
40     bool first = true;
41     bool addedFirst = false;
42     bool addedLast = false;
43     SkString offsets("[");
44     SkString* lastOffset = NULL;
45     for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
46         SkASSERT((*ptr)->getType() == SkSVGType_Stop);
47         SkSVGStop* stop = (SkSVGStop*) *ptr;
48         if (first && stop->f_offset.equals("0") == false) {
49             addedFirst = true;
50             offsets.append("0,");
51         }
52         SkString* thisOffset = &stop->f_offset;
53         if (lastOffset && thisOffset->equals(*lastOffset)) {
54             if (thisOffset->equals("1")) {
55                 offsets.remove(offsets.size() - 2, 2);
56                 offsets.append(".999,");
57             } else {
58                 SkASSERT(0); // !!! need to write this case
59             }
60         }
61         offsets.append(*thisOffset);
62         if (ptr == fChildren.end() - 1) { // last
63             if (stop->f_offset.equals("1") == false) {
64                 offsets.append(",1");
65                 addedLast = true;
66             }
67         } else
68             offsets.appendUnichar(',');
69         first = false;
70         lastOffset = thisOffset;
71     }
72     offsets.appendUnichar(']');
73     parser._addAttribute("offsets", offsets);
74     if (addedFirst)
75         parser.translate(*fChildren.begin(), defState);
76     for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++)
77         parser.translate(*ptr, defState);
78     if (addedLast)
79         parser.translate(*(fChildren.end() - 1), defState);
80 }
81 
translateGradientUnits(SkString & units)82 void SkSVGGradient::translateGradientUnits(SkString& units) {
83     // !!! no support for 'objectBoundingBox' yet
84     SkASSERT(strcmp(units.c_str(), "userSpaceOnUse") == 0);
85 }
86 
write(SkSVGParser & parser,SkString & baseColor)87 void SkSVGGradient::write(SkSVGParser& parser, SkString& baseColor) {
88     if (baseColor.c_str()[0] != '#')
89         return;
90     SkSVGPaint* saveHead = parser.fHead;
91     parser.fHead = &fPaintState;
92     parser.fSuppressPaint = true;
93     SkString originalID(f_id);
94     f_id.set("mask"); // write out gradient named given name + color (less initial #)
95     f_id.append(baseColor.c_str() + 1);
96     SkString originalColors;
97     for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
98         SkSVGStop* colorElement = (SkSVGStop*) *ptr;
99         SkString& color = colorElement->fPaintState.f_stopColor;
100         originalColors.append(color);
101         originalColors.appendUnichar(',');
102         SkASSERT(color.c_str()[0] == '#');
103         SkString replacement;
104         replacement.set("0x");
105         replacement.append(color.c_str() + 1, 2); // add stop colors using given color, turning existing stop color into alpha
106         SkASSERT(baseColor.c_str()[0] == '#');
107         SkASSERT(baseColor.size() == 7);
108         replacement.append(baseColor.c_str() + 1);
109         color.set(replacement);
110     }
111     translate(parser, true);
112     const char* originalPtr = originalColors.c_str(); // restore original gradient values
113     for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
114         SkSVGStop* color = (SkSVGStop*) *ptr;
115         const char* originalEnd = strchr(originalPtr, ',');
116         color->fPaintState.f_stopColor.set(originalPtr, originalEnd - originalPtr);
117         originalPtr = originalEnd + 1;
118     }
119     f_id.set(originalID);
120     parser.fSuppressPaint = false;
121     parser.fHead = saveHead;
122 }
123 
124