Home | History | Annotate | Download | only in svg
      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