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 "SkSVGGradient.h"
11 #include "SkSVGParser.h"
12 #include "SkSVGStop.h"
13
SkSVGGradient()14 SkSVGGradient::SkSVGGradient() {
15 }
16
getGradient()17 SkSVGElement* SkSVGGradient::getGradient() {
18 return this;
19 }
20
isDef()21 bool SkSVGGradient::isDef() {
22 return true;
23 }
24
isNotDef()25 bool SkSVGGradient::isNotDef() {
26 return false;
27 }
28
translate(SkSVGParser & parser,bool defState)29 void SkSVGGradient::translate(SkSVGParser& parser, bool defState) {
30 INHERITED::translate(parser, defState);
31 // !!! no support for 'objectBoundingBox' yet
32 bool first = true;
33 bool addedFirst = false;
34 bool addedLast = false;
35 SkString offsets("[");
36 SkString* lastOffset = NULL;
37 for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
38 SkASSERT((*ptr)->getType() == SkSVGType_Stop);
39 SkSVGStop* stop = (SkSVGStop*) *ptr;
40 if (first && stop->f_offset.equals("0") == false) {
41 addedFirst = true;
42 offsets.append("0,");
43 }
44 SkString* thisOffset = &stop->f_offset;
45 if (lastOffset && thisOffset->equals(*lastOffset)) {
46 if (thisOffset->equals("1")) {
47 offsets.remove(offsets.size() - 2, 2);
48 offsets.append(".999,");
49 } else {
50 SkASSERT(0); // !!! need to write this case
51 }
52 }
53 offsets.append(*thisOffset);
54 if (ptr == fChildren.end() - 1) { // last
55 if (stop->f_offset.equals("1") == false) {
56 offsets.append(",1");
57 addedLast = true;
58 }
59 } else
60 offsets.appendUnichar(',');
61 first = false;
62 lastOffset = thisOffset;
63 }
64 offsets.appendUnichar(']');
65 parser._addAttribute("offsets", offsets);
66 if (addedFirst)
67 parser.translate(*fChildren.begin(), defState);
68 for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++)
69 parser.translate(*ptr, defState);
70 if (addedLast)
71 parser.translate(*(fChildren.end() - 1), defState);
72 }
73
translateGradientUnits(SkString & units)74 void SkSVGGradient::translateGradientUnits(SkString& units) {
75 // !!! no support for 'objectBoundingBox' yet
76 SkASSERT(strcmp(units.c_str(), "userSpaceOnUse") == 0);
77 }
78
write(SkSVGParser & parser,SkString & baseColor)79 void SkSVGGradient::write(SkSVGParser& parser, SkString& baseColor) {
80 if (baseColor.c_str()[0] != '#')
81 return;
82 SkSVGPaint* saveHead = parser.fHead;
83 parser.fHead = &fPaintState;
84 parser.fSuppressPaint = true;
85 SkString originalID(f_id);
86 f_id.set("mask"); // write out gradient named given name + color (less initial #)
87 f_id.append(baseColor.c_str() + 1);
88 SkString originalColors;
89 for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
90 SkSVGStop* colorElement = (SkSVGStop*) *ptr;
91 SkString& color = colorElement->fPaintState.f_stopColor;
92 originalColors.append(color);
93 originalColors.appendUnichar(',');
94 SkASSERT(color.c_str()[0] == '#');
95 SkString replacement;
96 replacement.set("0x");
97 replacement.append(color.c_str() + 1, 2); // add stop colors using given color, turning existing stop color into alpha
98 SkASSERT(baseColor.c_str()[0] == '#');
99 SkASSERT(baseColor.size() == 7);
100 replacement.append(baseColor.c_str() + 1);
101 color.set(replacement);
102 }
103 translate(parser, true);
104 const char* originalPtr = originalColors.c_str(); // restore original gradient values
105 for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
106 SkSVGStop* color = (SkSVGStop*) *ptr;
107 const char* originalEnd = strchr(originalPtr, ',');
108 color->fPaintState.f_stopColor.set(originalPtr, originalEnd - originalPtr);
109 originalPtr = originalEnd + 1;
110 }
111 f_id.set(originalID);
112 parser.fSuppressPaint = false;
113 parser.fHead = saveHead;
114 }
115