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 22 SkSVGGradient::SkSVGGradient() { 23 } 24 25 SkSVGElement* SkSVGGradient::getGradient() { 26 return this; 27 } 28 29 bool SkSVGGradient::isDef() { 30 return true; 31 } 32 33 bool SkSVGGradient::isNotDef() { 34 return false; 35 } 36 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 82 void SkSVGGradient::translateGradientUnits(SkString& units) { 83 // !!! no support for 'objectBoundingBox' yet 84 SkASSERT(strcmp(units.c_str(), "userSpaceOnUse") == 0); 85 } 86 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