gfx/skia/trunk/src/svg/SkSVGPaintState.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
    10 #include "SkSVGPaintState.h"
    11 #include "SkSVGElements.h"
    12 #include "SkSVGParser.h"
    13 #include "SkParse.h"
    15 SkSVGAttribute SkSVGPaint::gAttributes[] = {
    16     SVG_LITERAL_ATTRIBUTE(clip-path, f_clipPath),
    17     SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule),
    18     SVG_LITERAL_ATTRIBUTE(enable-background, f_enableBackground),
    19     SVG_ATTRIBUTE(fill),
    20     SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule),
    21     SVG_ATTRIBUTE(filter),
    22     SVG_LITERAL_ATTRIBUTE(font-family, f_fontFamily),
    23     SVG_LITERAL_ATTRIBUTE(font-size, f_fontSize),
    24     SVG_LITERAL_ATTRIBUTE(letter-spacing, f_letterSpacing),
    25     SVG_ATTRIBUTE(mask),
    26     SVG_ATTRIBUTE(opacity),
    27     SVG_LITERAL_ATTRIBUTE(stop-color, f_stopColor),
    28     SVG_LITERAL_ATTRIBUTE(stop-opacity, f_stopOpacity),
    29     SVG_ATTRIBUTE(stroke),
    30     SVG_LITERAL_ATTRIBUTE(stroke-dasharray, f_strokeDasharray),
    31     SVG_LITERAL_ATTRIBUTE(stroke-linecap, f_strokeLinecap),
    32     SVG_LITERAL_ATTRIBUTE(stroke-linejoin, f_strokeLinejoin),
    33     SVG_LITERAL_ATTRIBUTE(stroke-miterlimit, f_strokeMiterlimit),
    34     SVG_LITERAL_ATTRIBUTE(stroke-width, f_strokeWidth),
    35     SVG_ATTRIBUTE(style),
    36     SVG_ATTRIBUTE(transform)
    37 };
    39 const int SkSVGPaint::kAttributesSize = SK_ARRAY_COUNT(SkSVGPaint::gAttributes);
    41 SkSVGPaint::SkSVGPaint() : fNext(NULL) {
    42 }
    44 SkString* SkSVGPaint::operator[](int index) {
    45     SkASSERT(index >= 0);
    46     SkASSERT(index < &fTerminal - &fInitial);
    47     SkASSERT(&fTerminal - &fInitial == kTerminal - kInitial);
    48     SkString* result = &fInitial + index + 1;
    49     return result;
    50 }
    52 void SkSVGPaint::addAttribute(SkSVGParser& parser, int attrIndex,
    53         const char* attrValue, size_t attrLength) {
    54     SkString* attr = (*this)[attrIndex];
    55     switch(attrIndex) {
    56         case kClipPath:
    57         case kClipRule:
    58         case kEnableBackground:
    59         case kFill:
    60         case kFillRule:
    61         case kFilter:
    62         case kFontFamily:
    63         case kFontSize:
    64         case kLetterSpacing:
    65         case kMask:
    66         case kOpacity:
    67         case kStopColor:
    68         case kStopOpacity:
    69         case kStroke:
    70         case kStroke_Dasharray:
    71         case kStroke_Linecap:
    72         case kStroke_Linejoin:
    73         case kStroke_Miterlimit:
    74         case kStroke_Width:
    75         case kTransform:
    76             attr->set(attrValue, attrLength);
    77             return;
    78         case kStyle: {
    79             // iterate through colon / semi-colon delimited pairs
    80             int pairs = SkParse::Count(attrValue, ';');
    81             const char* attrEnd = attrValue + attrLength;
    82             do {
    83                 const char* end = strchr(attrValue, ';');
    84                 if (end == NULL)
    85                     end = attrEnd;
    86                 const char* delimiter = strchr(attrValue, ':');
    87                 SkASSERT(delimiter != 0 && delimiter < end);
    88                 int index = parser.findAttribute(this, attrValue, (int) (delimiter - attrValue), true);
    89                 SkASSERT(index >= 0);
    90                 delimiter++;
    91                 addAttribute(parser, index, delimiter, (int) (end - delimiter));
    92                 attrValue = end + 1;
    93             } while (--pairs);
    94             return;
    95             }
    96         default:
    97             SkASSERT(0);
    98     }
    99 }
   101 bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) {
   102     SkSVGPaint current;
   103     SkSVGPaint* walking = parser.fHead;
   104     int index;
   105     while (walking != NULL) {
   106         for (index = kInitial + 1; index < kTerminal; index++) {
   107             SkString* lastAttr = (*walking)[index];
   108             if (lastAttr->size() == 0)
   109                 continue;
   110             if (current[index]->size() > 0)
   111                 continue;
   112             current[index]->set(*lastAttr);
   113         }
   114         walking = walking->fNext;
   115     }
   116     bool paintChanged = false;
   117     SkSVGPaint& lastState = parser.fLastFlush;
   118     if (isFlushable == false) {
   119         if (isDef == true) {
   120             if (current.f_mask.size() > 0 && current.f_mask.equals(lastState.f_mask) == false) {
   121                 SkSVGElement* found;
   122                 const char* idStart = strchr(current.f_mask.c_str(), '#');
   123                 SkASSERT(idStart);
   124                 SkString id(idStart + 1, strlen(idStart) - 2);
   125                 bool itsFound = parser.fIDs.find(id.c_str(), &found);
   126                 SkASSERT(itsFound);
   127                 SkSVGElement* gradient = found->getGradient();
   128                 if (gradient) {
   129                     gradient->write(parser, current.f_fill);
   130                     gradient->write(parser, current.f_stroke);
   131                 }
   132             }
   133         }
   134         goto setLast;
   135     }
   136     {
   137         bool changed[kTerminal];
   138         memset(changed, 0, sizeof(changed));
   139         for (index = kInitial + 1; index < kTerminal; index++) {
   140             if (index == kTransform || index == kClipPath || index == kStopColor || index == kStopOpacity ||
   141                     index == kClipRule || index == kFillRule)
   142                 continue;
   143             SkString* lastAttr = lastState[index];
   144             SkString* currentAttr = current[index];
   145             paintChanged |= changed[index] = lastAttr->equals(*currentAttr) == false;
   146         }
   147         if (paintChanged) {
   148             if (current.f_mask.size() > 0) {
   149                 if (current.f_fill.equals("none") == false && strncmp(current.f_fill.c_str(), "url(#", 5) != 0) {
   150                     SkASSERT(current.f_fill.c_str()[0] == '#');
   151                     SkString replacement("url(#mask");
   152                     replacement.append(current.f_fill.c_str() + 1);
   153                     replacement.appendUnichar(')');
   154                     current.f_fill.set(replacement);
   155                 }
   156                 if (current.f_stroke.equals("none") == false && strncmp(current.f_stroke.c_str(), "url(#", 5) != 0) {
   157                     SkASSERT(current.f_stroke.c_str()[0] == '#');
   158                     SkString replacement("url(#mask");
   159                     replacement.append(current.f_stroke.c_str() + 1);
   160                     replacement.appendUnichar(')');
   161                     current.f_stroke.set(replacement);
   162                 }
   163             }
   164             if (current.f_fill.equals("none") && current.f_stroke.equals("none"))
   165                 current.f_opacity.set("0");
   166             if (parser.fSuppressPaint == false) {
   167                 parser._startElement("paint");
   168                 bool success = writeChangedAttributes(parser, current, changed);
   169                 if (success == false)
   170                     return paintChanged;
   171                 success = writeChangedElements(parser, current, changed);
   172                 if (success == false)
   173                     return paintChanged;
   174                 parser._endElement(); // paint
   175             }
   176         }
   177     }
   178 setLast:
   179     for (index = kInitial + 1; index < kTerminal; index++) {
   180         SkString* lastAttr = lastState[index];
   181         SkString* currentAttr = current[index];
   182         lastAttr->set(*currentAttr);
   183     }
   184     return paintChanged;
   185 }
   187 int SkSVGPaint::getAttributes(const SkSVGAttribute** attrPtr) {
   188     *attrPtr = gAttributes;
   189     return kAttributesSize;
   190 }
   192 void SkSVGPaint::setSave(SkSVGParser& parser) {
   193     SkTDArray<SkString*> clips;
   194     SkSVGPaint* walking = parser.fHead;
   195     int index;
   196     SkMatrix sum;
   197     sum.reset();
   198     while (walking != NULL) {
   199         for (index = kInitial + 1; index < kTerminal; index++) {
   200             SkString* lastAttr = (*walking)[index];
   201             if (lastAttr->size() == 0)
   202                 continue;
   203             if (index == kTransform) {
   204                 const char* str = lastAttr->c_str();
   205                 SkASSERT(strncmp(str, "matrix(", 7) == 0);
   206                 str += 6;
   207                 const char* strEnd = strrchr(str, ')');
   208                 SkASSERT(strEnd != NULL);
   209                 SkString mat(str, strEnd - str);
   210                 SkSVGParser::ConvertToArray(mat);
   211                 SkScalar values[6];
   212                 SkParse::FindScalars(mat.c_str() + 1, values, 6);
   213                 SkMatrix matrix;
   214                 matrix.reset();
   215                 matrix.setScaleX(values[0]);
   216                 matrix.setSkewY(values[1]);
   217                 matrix.setSkewX(values[2]);
   218                 matrix.setScaleY(values[3]);
   219                 matrix.setTranslateX(values[4]);
   220                 matrix.setTranslateY(values[5]);
   221                 sum.setConcat(matrix, sum);
   222                 continue;
   223             }
   224             if ( index == kClipPath)
   225                 *clips.insert(0) = lastAttr;
   226         }
   227         walking = walking->fNext;
   228     }
   229     if ((sum == parser.fLastTransform) == false) {
   230         SkMatrix inverse;
   231         bool success = parser.fLastTransform.invert(&inverse);
   232         SkASSERT(success == true);
   233         SkMatrix output;
   234         output.setConcat(inverse, sum);
   235         parser.fLastTransform = sum;
   236         SkString outputStr;
   237         outputStr.appendUnichar('[');
   238         outputStr.appendScalar(output.getScaleX());
   239         outputStr.appendUnichar(',');
   240         outputStr.appendScalar(output.getSkewX());
   241         outputStr.appendUnichar(',');
   242         outputStr.appendScalar(output.getTranslateX());
   243         outputStr.appendUnichar(',');
   244         outputStr.appendScalar(output.getSkewY());
   245         outputStr.appendUnichar(',');
   246         outputStr.appendScalar(output.getScaleY());
   247         outputStr.appendUnichar(',');
   248         outputStr.appendScalar(output.getTranslateY());
   249         outputStr.appendUnichar(',');
   250         outputStr.appendScalar(output.getPerspX());
   251         outputStr.appendUnichar(',');
   252         outputStr.appendScalar(output.getPerspY());
   253         outputStr.append(",1]");
   254         parser._startElement("matrix");
   255         parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size());
   256         parser._endElement();
   257     }
   258 #if 0   // incomplete
   259     if (parser.fTransformClips.size() > 0) {
   260         // need to reset the clip when the 'g' scope is ended
   261         parser._startElement("add");
   262         const char* start = strchr(current->f_clipPath.c_str(), '#') + 1;
   263         SkASSERT(start);
   264         parser._addAttributeLen("use", start, strlen(start) - 1);
   265         parser._endElement();   // clip
   266     }
   267 #endif
   268 }
   270 bool SkSVGPaint::writeChangedAttributes(SkSVGParser& parser,
   271         SkSVGPaint& current, bool* changed) {
   272     SkSVGPaint& lastState = parser.fLastFlush;
   273     for (int index = kInitial + 1; index < kTerminal; index++) {
   274         if (changed[index] == false)
   275                 continue;
   276         SkString* topAttr = current[index];
   277         size_t attrLength = topAttr->size();
   278         if (attrLength == 0)
   279             continue;
   280         const char* attrValue = topAttr->c_str();
   281         SkString* lastAttr = lastState[index];
   282         switch(index) {
   283             case kClipPath:
   284             case kClipRule:
   285             case kEnableBackground:
   286                 break;
   287             case kFill:
   288                 if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
   289                     parser._addAttribute("stroke", "false");
   290                 goto fillStrokeAttrCommon;
   291             case kFillRule:
   292             case kFilter:
   293             case kFontFamily:
   294                 break;
   295             case kFontSize:
   296                 parser._addAttributeLen("textSize", attrValue, attrLength);
   297                 break;
   298             case kLetterSpacing:
   299                 parser._addAttributeLen("textTracking", attrValue, attrLength);
   300                 break;
   301             case kMask:
   302                 break;
   303             case kOpacity:
   304                 break;
   305             case kStopColor:
   306                 break;
   307             case kStopOpacity:
   308                 break;
   309             case kStroke:
   310                 if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
   311                     parser._addAttribute("stroke", "true");
   312 fillStrokeAttrCommon:
   313                 if (strncmp(attrValue, "url(", 4) == 0) {
   314                     SkASSERT(attrValue[4] == '#');
   315                     const char* idStart = attrValue + 5;
   316                     const char* idEnd = strrchr(attrValue, ')');
   317                     SkASSERT(idStart < idEnd);
   318                     SkString id(idStart, idEnd - idStart);
   319                     SkSVGElement* found;
   320                     if (strncmp(id.c_str(), "mask", 4) != 0) {
   321                         bool itsFound = parser.fIDs.find(id.c_str(), &found);
   322                         SkASSERT(itsFound);
   323                         SkASSERT(found->getType() == SkSVGType_LinearGradient ||
   324                             found->getType() == SkSVGType_RadialGradient);
   325                     }
   326                     parser._addAttribute("shader", id.c_str());
   327                 }
   328                 break;
   329             case kStroke_Dasharray:
   330                 break;
   331             case kStroke_Linecap:
   332                 parser._addAttributeLen("strokeCap", attrValue, attrLength);
   333                 break;
   334             case kStroke_Linejoin:
   335                 parser._addAttributeLen("strokeJoin", attrValue, attrLength);
   336                 break;
   337             case kStroke_Miterlimit:
   338                 parser._addAttributeLen("strokeMiter", attrValue, attrLength);
   339                 break;
   340             case kStroke_Width:
   341                 parser._addAttributeLen("strokeWidth", attrValue, attrLength);
   342             case kStyle:
   343             case kTransform:
   344                 break;
   345         default:
   346             SkASSERT(0);
   347             return false;
   348         }
   349     }
   350     return true;
   351 }
   353 bool SkSVGPaint::writeChangedElements(SkSVGParser& parser,
   354         SkSVGPaint& current, bool* changed) {
   355     SkSVGPaint& lastState = parser.fLastFlush;
   356     for (int index = kInitial + 1; index < kTerminal; index++) {
   357         SkString* topAttr = current[index];
   358         size_t attrLength = topAttr->size();
   359         if (attrLength == 0)
   360             continue;
   361         const char* attrValue = topAttr->c_str();
   362         SkString* lastAttr = lastState[index];
   363         switch(index) {
   364             case kClipPath:
   365             case kClipRule:
   366                 // !!! need to add this outside of paint
   367                 break;
   368             case kEnableBackground:
   369                 // !!! don't know what to do with this
   370                 break;
   371             case kFill:
   372                 goto addColor;
   373             case kFillRule:
   374             case kFilter:
   375                 break;
   376             case kFontFamily:
   377                 parser._startElement("typeface");
   378                 parser._addAttributeLen("fontName", attrValue, attrLength);
   379                 parser._endElement();   // typeface
   380                 break;
   381             case kFontSize:
   382             case kLetterSpacing:
   383                 break;
   384             case kMask:
   385             case kOpacity:
   386                 if (changed[kStroke] == false && changed[kFill] == false) {
   387                     parser._startElement("color");
   388                     SkString& opacity = current.f_opacity;
   389                     parser._addAttributeLen("color", parser.fLastColor.c_str(), parser.fLastColor.size());
   390                     parser._addAttributeLen("alpha", opacity.c_str(), opacity.size());
   391                     parser._endElement();   // color
   392                 }
   393                 break;
   394             case kStopColor:
   395                 break;
   396             case kStopOpacity:
   397                 break;
   398             case kStroke:
   399 addColor:
   400                 if (strncmp(lastAttr->c_str(), "url(", 4) == 0 && strncmp(attrValue, "url(", 4) != 0) {
   401                     parser._startElement("shader");
   402                     parser._endElement();
   403                 }
   404                 if (topAttr->equals(*lastAttr))
   405                     continue;
   406                 {
   407                     bool urlRef = strncmp(attrValue, "url(", 4) == 0;
   408                     bool colorNone = strcmp(attrValue, "none") == 0;
   409                     bool lastEqual = parser.fLastColor.equals(attrValue, attrLength);
   410                     bool newColor = urlRef == false && colorNone == false && lastEqual == false;
   411                     if (newColor || changed[kOpacity]) {
   412                         parser._startElement("color");
   413                         if (newColor || changed[kOpacity]) {
   414                             parser._addAttributeLen("color", attrValue, attrLength);
   415                             parser.fLastColor.set(attrValue, attrLength);
   416                         }
   417                         if (changed[kOpacity]) {
   418                             SkString& opacity = current.f_opacity;
   419                             parser._addAttributeLen("alpha", opacity.c_str(), opacity.size());
   420                         }
   421                         parser._endElement();   // color
   422                     }
   423                 }
   424                 break;
   425             case kStroke_Dasharray:
   426                 parser._startElement("dash");
   427                 SkSVGParser::ConvertToArray(*topAttr);
   428                 parser._addAttribute("intervals", topAttr->c_str());
   429                 parser._endElement();   // dash
   430             break;
   431             case kStroke_Linecap:
   432             case kStroke_Linejoin:
   433             case kStroke_Miterlimit:
   434             case kStroke_Width:
   435             case kStyle:
   436             case kTransform:
   437                 break;
   438         default:
   439             SkASSERT(0);
   440             return false;
   441         }
   442     }
   443     return true;
   444 }
   446 void SkSVGPaint::Push(SkSVGPaint** head, SkSVGPaint* newRecord) {
   447     newRecord->fNext = *head;
   448     *head = newRecord;
   449 }
   451 void SkSVGPaint::Pop(SkSVGPaint** head) {
   452     SkSVGPaint* next = (*head)->fNext;
   453     *head = next;
   454 }

mercurial