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.

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

mercurial