gfx/skia/trunk/src/pdf/SkPDFGraphicState.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.

     1 /*
     2  * Copyright 2011 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkPDFFormXObject.h"
     9 #include "SkPDFGraphicState.h"
    10 #include "SkPDFUtils.h"
    11 #include "SkStream.h"
    12 #include "SkTypes.h"
    14 static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
    15     switch (mode) {
    16         case SkXfermode::kSrcOver_Mode:    return "Normal";
    17         case SkXfermode::kMultiply_Mode:   return "Multiply";
    18         case SkXfermode::kScreen_Mode:     return "Screen";
    19         case SkXfermode::kOverlay_Mode:    return "Overlay";
    20         case SkXfermode::kDarken_Mode:     return "Darken";
    21         case SkXfermode::kLighten_Mode:    return "Lighten";
    22         case SkXfermode::kColorDodge_Mode: return "ColorDodge";
    23         case SkXfermode::kColorBurn_Mode:  return "ColorBurn";
    24         case SkXfermode::kHardLight_Mode:  return "HardLight";
    25         case SkXfermode::kSoftLight_Mode:  return "SoftLight";
    26         case SkXfermode::kDifference_Mode: return "Difference";
    27         case SkXfermode::kExclusion_Mode:  return "Exclusion";
    28         case SkXfermode::kHue_Mode:        return "Hue";
    29         case SkXfermode::kSaturation_Mode: return "Saturation";
    30         case SkXfermode::kColor_Mode:      return "Color";
    31         case SkXfermode::kLuminosity_Mode: return "Luminosity";
    33         // These are handled in SkPDFDevice::setUpContentEntry.
    34         case SkXfermode::kClear_Mode:
    35         case SkXfermode::kSrc_Mode:
    36         case SkXfermode::kDst_Mode:
    37         case SkXfermode::kDstOver_Mode:
    38         case SkXfermode::kSrcIn_Mode:
    39         case SkXfermode::kDstIn_Mode:
    40         case SkXfermode::kSrcOut_Mode:
    41         case SkXfermode::kDstOut_Mode:
    42         case SkXfermode::kSrcATop_Mode:
    43         case SkXfermode::kDstATop_Mode:
    44         case SkXfermode::kModulate_Mode:
    45             return "Normal";
    47         // TODO(vandebo): Figure out if we can support more of these modes.
    48         case SkXfermode::kXor_Mode:
    49         case SkXfermode::kPlus_Mode:
    50             return NULL;
    51     }
    52     return NULL;
    53 }
    55 SkPDFGraphicState::~SkPDFGraphicState() {
    56     SkAutoMutexAcquire lock(CanonicalPaintsMutex());
    57     if (!fSMask) {
    58         int index = Find(fPaint);
    59         SkASSERT(index >= 0);
    60         SkASSERT(CanonicalPaints()[index].fGraphicState == this);
    61         CanonicalPaints().removeShuffle(index);
    62     }
    63     fResources.unrefAll();
    64 }
    66 void SkPDFGraphicState::getResources(
    67         const SkTSet<SkPDFObject*>& knownResourceObjects,
    68         SkTSet<SkPDFObject*>* newResourceObjects) {
    69     GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
    70 }
    72 void SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
    73                                    bool indirect) {
    74     populateDict();
    75     SkPDFDict::emitObject(stream, catalog, indirect);
    76 }
    78 // static
    79 size_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
    80     populateDict();
    81     return SkPDFDict::getOutputSize(catalog, indirect);
    82 }
    84 // static
    85 SkTDArray<SkPDFGraphicState::GSCanonicalEntry>&
    86 SkPDFGraphicState::CanonicalPaints() {
    87     // This initialization is only thread safe with gcc.
    88     static SkTDArray<SkPDFGraphicState::GSCanonicalEntry> gCanonicalPaints;
    89     return gCanonicalPaints;
    90 }
    92 // static
    93 SkBaseMutex& SkPDFGraphicState::CanonicalPaintsMutex() {
    94     // This initialization is only thread safe with gcc or when
    95     // POD-style mutex initialization is used.
    96     SK_DECLARE_STATIC_MUTEX(gCanonicalPaintsMutex);
    97     return gCanonicalPaintsMutex;
    98 }
   100 // static
   101 SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
   102         const SkPaint& paint) {
   103     SkAutoMutexAcquire lock(CanonicalPaintsMutex());
   104     int index = Find(paint);
   105     if (index >= 0) {
   106         CanonicalPaints()[index].fGraphicState->ref();
   107         return CanonicalPaints()[index].fGraphicState;
   108     }
   109     GSCanonicalEntry newEntry(new SkPDFGraphicState(paint));
   110     CanonicalPaints().push(newEntry);
   111     return newEntry.fGraphicState;
   112 }
   114 // static
   115 SkPDFObject* SkPDFGraphicState::GetInvertFunction() {
   116     // This assumes that canonicalPaintsMutex is held.
   117     static SkPDFStream* invertFunction = NULL;
   118     if (!invertFunction) {
   119         // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
   120         // a type 2 function, so we use a type 4 function.
   121         SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray);
   122         domainAndRange->reserve(2);
   123         domainAndRange->appendInt(0);
   124         domainAndRange->appendInt(1);
   126         static const char psInvert[] = "{1 exch sub}";
   127         SkAutoTUnref<SkMemoryStream> psInvertStream(
   128             new SkMemoryStream(&psInvert, strlen(psInvert), true));
   130         invertFunction = new SkPDFStream(psInvertStream.get());
   131         invertFunction->insertInt("FunctionType", 4);
   132         invertFunction->insert("Domain", domainAndRange.get());
   133         invertFunction->insert("Range", domainAndRange.get());
   134     }
   135     return invertFunction;
   136 }
   138 // static
   139 SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
   140         SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) {
   141     // The practical chances of using the same mask more than once are unlikely
   142     // enough that it's not worth canonicalizing.
   143     SkAutoMutexAcquire lock(CanonicalPaintsMutex());
   145     SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
   146     if (sMaskMode == kAlpha_SMaskMode) {
   147         sMaskDict->insertName("S", "Alpha");
   148     } else if (sMaskMode == kLuminosity_SMaskMode) {
   149         sMaskDict->insertName("S", "Luminosity");
   150     }
   151     sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref();
   153     SkPDFGraphicState* result = new SkPDFGraphicState;
   154     result->fPopulated = true;
   155     result->fSMask = true;
   156     result->insertName("Type", "ExtGState");
   157     result->insert("SMask", sMaskDict.get());
   158     result->fResources.push(sMask);
   159     sMask->ref();
   161     if (invert) {
   162         SkPDFObject* invertFunction = GetInvertFunction();
   163         result->fResources.push(invertFunction);
   164         invertFunction->ref();
   165         sMaskDict->insert("TR", new SkPDFObjRef(invertFunction))->unref();
   166     }
   168     return result;
   169 }
   171 // static
   172 SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
   173     SkAutoMutexAcquire lock(CanonicalPaintsMutex());
   174     static SkPDFGraphicState* noSMaskGS = NULL;
   175     if (!noSMaskGS) {
   176         noSMaskGS = new SkPDFGraphicState;
   177         noSMaskGS->fPopulated = true;
   178         noSMaskGS->fSMask = true;
   179         noSMaskGS->insertName("Type", "ExtGState");
   180         noSMaskGS->insertName("SMask", "None");
   181     }
   182     noSMaskGS->ref();
   183     return noSMaskGS;
   184 }
   186 // static
   187 int SkPDFGraphicState::Find(const SkPaint& paint) {
   188     GSCanonicalEntry search(&paint);
   189     return CanonicalPaints().find(search);
   190 }
   192 SkPDFGraphicState::SkPDFGraphicState()
   193     : fPopulated(false),
   194       fSMask(false) {
   195 }
   197 SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
   198     : fPaint(paint),
   199       fPopulated(false),
   200       fSMask(false) {
   201 }
   203 // populateDict and operator== have to stay in sync with each other.
   204 void SkPDFGraphicState::populateDict() {
   205     if (!fPopulated) {
   206         fPopulated = true;
   207         insertName("Type", "ExtGState");
   209         SkAutoTUnref<SkPDFScalar> alpha(
   210             new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF)));
   211         insert("CA", alpha.get());
   212         insert("ca", alpha.get());
   214         SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
   215         SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
   216         SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
   217         SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
   218         SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2);
   219         insertInt("LC", fPaint.getStrokeCap());
   221         SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
   222         SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
   223         SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
   224         SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
   225         SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2);
   226         insertInt("LJ", fPaint.getStrokeJoin());
   228         insertScalar("LW", fPaint.getStrokeWidth());
   229         insertScalar("ML", fPaint.getStrokeMiter());
   230         insert("SA", new SkPDFBool(true))->unref();  // Auto stroke adjustment.
   232         SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
   233         // If asMode fails, default to kSrcOver_Mode.
   234         if (fPaint.getXfermode())
   235             fPaint.getXfermode()->asMode(&xfermode);
   236         // If we don't support the mode, just use kSrcOver_Mode.
   237         if (xfermode < 0 || xfermode > SkXfermode::kLastMode ||
   238                 blend_mode_from_xfermode(xfermode) == NULL) {
   239             xfermode = SkXfermode::kSrcOver_Mode;
   240             NOT_IMPLEMENTED("unsupported xfermode", false);
   241         }
   242         insertName("BM", blend_mode_from_xfermode(xfermode));
   243     }
   244 }
   246 // We're only interested in some fields of the SkPaint, so we have a custom
   247 // operator== function.
   248 bool SkPDFGraphicState::GSCanonicalEntry::operator==(
   249         const SkPDFGraphicState::GSCanonicalEntry& gs) const {
   250     const SkPaint* a = fPaint;
   251     const SkPaint* b = gs.fPaint;
   252     SkASSERT(a != NULL);
   253     SkASSERT(b != NULL);
   255     if (SkColorGetA(a->getColor()) != SkColorGetA(b->getColor()) ||
   256            a->getStrokeCap() != b->getStrokeCap() ||
   257            a->getStrokeJoin() != b->getStrokeJoin() ||
   258            a->getStrokeWidth() != b->getStrokeWidth() ||
   259            a->getStrokeMiter() != b->getStrokeMiter()) {
   260         return false;
   261     }
   263     SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode;
   264     SkXfermode* aXfermode = a->getXfermode();
   265     if (aXfermode) {
   266         aXfermode->asMode(&aXfermodeName);
   267     }
   268     if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
   269             blend_mode_from_xfermode(aXfermodeName) == NULL) {
   270         aXfermodeName = SkXfermode::kSrcOver_Mode;
   271     }
   272     const char* aXfermodeString = blend_mode_from_xfermode(aXfermodeName);
   273     SkASSERT(aXfermodeString != NULL);
   275     SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
   276     SkXfermode* bXfermode = b->getXfermode();
   277     if (bXfermode) {
   278         bXfermode->asMode(&bXfermodeName);
   279     }
   280     if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
   281             blend_mode_from_xfermode(bXfermodeName) == NULL) {
   282         bXfermodeName = SkXfermode::kSrcOver_Mode;
   283     }
   284     const char* bXfermodeString = blend_mode_from_xfermode(bXfermodeName);
   285     SkASSERT(bXfermodeString != NULL);
   287     return strcmp(aXfermodeString, bXfermodeString) == 0;
   288 }

mercurial