14ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org/*
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2011 Google Inc.
34ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org *
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
64ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org */
74ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
8e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org#include "SkPDFFormXObject.h"
94ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org#include "SkPDFGraphicState.h"
108c32f5efcf180adc0cbf8ad3a7cac691eba42f20vandebo@chromium.org#include "SkPDFUtils.h"
114ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org#include "SkStream.h"
1219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org#include "SkTypes.h"
1319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
14e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.orgstatic const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
1519caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    switch (mode) {
1619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSrcOver_Mode:    return "Normal";
17cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        // kModulate is not really like multipy but similar most of the time.
18f0099aa86b3a1086e62837426097f620fa4c0eeaskia.committer@gmail.com        case SkXfermode::kModulate_Mode:
19cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        case SkXfermode::kMultiply_Mode:   return "Multiply";
2019caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kScreen_Mode:     return "Screen";
2119caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kOverlay_Mode:    return "Overlay";
2219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDarken_Mode:     return "Darken";
2319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kLighten_Mode:    return "Lighten";
2419caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kColorDodge_Mode: return "ColorDodge";
2519caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kColorBurn_Mode:  return "ColorBurn";
2619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kHardLight_Mode:  return "HardLight";
2719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSoftLight_Mode:  return "SoftLight";
2819caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDifference_Mode: return "Difference";
2919caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kExclusion_Mode:  return "Exclusion";
30cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        case SkXfermode::kHue_Mode:        return "Hue";
31cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        case SkXfermode::kSaturation_Mode: return "Saturation";
32cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        case SkXfermode::kColor_Mode:      return "Color";
33cb608f40e52e6eb81361102f1437587438a1012ccommit-bot@chromium.org        case SkXfermode::kLuminosity_Mode: return "Luminosity";
3419caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
35a6cf7e9cd05d84108d7668e9e1bde927bee7a9f5vandebo@chromium.org        // These are handled in SkPDFDevice::setUpContentEntry.
3619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kClear_Mode:
3719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSrc_Mode:
3819caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDst_Mode:
3919caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDstOver_Mode:
4019caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSrcIn_Mode:
4119caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDstIn_Mode:
4219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSrcOut_Mode:
4319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDstOut_Mode:
44e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org            return "Normal";
45e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
46c0db31ffa3b2863d27f630b4809036f8fcc74c7ectguil@chromium.org        // TODO(vandebo): Figure out if we can support more of these modes.
4719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kSrcATop_Mode:
4819caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kDstATop_Mode:
4919caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kXor_Mode:
5019caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        case SkXfermode::kPlus_Mode:
5119caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org            return NULL;
5219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    }
5319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    return NULL;
5419caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org}
5519caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
564ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgSkPDFGraphicState::~SkPDFGraphicState() {
5709e900419f232872200a76c64357b105531791c4reed@google.com    SkAutoMutexAcquire lock(CanonicalPaintsMutex());
58e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    if (!fSMask) {
5909e900419f232872200a76c64357b105531791c4reed@google.com        int index = Find(fPaint);
60e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org        SkASSERT(index >= 0);
61413a85d9b0ff773b6a4422d918a3817f0cdfe33fvandebo@chromium.org        SkASSERT(CanonicalPaints()[index].fGraphicState == this);
6209e900419f232872200a76c64357b105531791c4reed@google.com        CanonicalPaints().removeShuffle(index);
63e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    }
64e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    fResources.unrefAll();
65e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org}
66e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
6709b4813b6bd356d371952c4346f1f9fbe02fdfceedisonn@google.comvoid SkPDFGraphicState::getResources(
6809b4813b6bd356d371952c4346f1f9fbe02fdfceedisonn@google.com        const SkTSet<SkPDFObject*>& knownResourceObjects,
6909b4813b6bd356d371952c4346f1f9fbe02fdfceedisonn@google.com        SkTSet<SkPDFObject*>* newResourceObjects) {
7009b4813b6bd356d371952c4346f1f9fbe02fdfceedisonn@google.com    GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
714ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
724ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
734ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgvoid SkPDFGraphicState::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
744ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org                                   bool indirect) {
754ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    populateDict();
764ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    SkPDFDict::emitObject(stream, catalog, indirect);
774ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
784ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
7919caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org// static
804ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgsize_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
814ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    populateDict();
824ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    return SkPDFDict::getOutputSize(catalog, indirect);
834ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
844ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
854ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// static
864ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgSkTDArray<SkPDFGraphicState::GSCanonicalEntry>&
8709e900419f232872200a76c64357b105531791c4reed@google.comSkPDFGraphicState::CanonicalPaints() {
884ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    // This initialization is only thread safe with gcc.
894ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    static SkTDArray<SkPDFGraphicState::GSCanonicalEntry> gCanonicalPaints;
904ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    return gCanonicalPaints;
914ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
924ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
934ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// static
9400819c385f318d9219e9a033fe23a1fa71ca40e5digit@google.comSkBaseMutex& SkPDFGraphicState::CanonicalPaintsMutex() {
9500819c385f318d9219e9a033fe23a1fa71ca40e5digit@google.com    // This initialization is only thread safe with gcc or when
9600819c385f318d9219e9a033fe23a1fa71ca40e5digit@google.com    // POD-style mutex initialization is used.
9700819c385f318d9219e9a033fe23a1fa71ca40e5digit@google.com    SK_DECLARE_STATIC_MUTEX(gCanonicalPaintsMutex);
984ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    return gCanonicalPaintsMutex;
994ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
1004ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
1014ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// static
10209e900419f232872200a76c64357b105531791c4reed@google.comSkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
1034ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        const SkPaint& paint) {
10409e900419f232872200a76c64357b105531791c4reed@google.com    SkAutoMutexAcquire lock(CanonicalPaintsMutex());
10509e900419f232872200a76c64357b105531791c4reed@google.com    int index = Find(paint);
1064ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    if (index >= 0) {
10709e900419f232872200a76c64357b105531791c4reed@google.com        CanonicalPaints()[index].fGraphicState->ref();
10809e900419f232872200a76c64357b105531791c4reed@google.com        return CanonicalPaints()[index].fGraphicState;
1094ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    }
1104ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    GSCanonicalEntry newEntry(new SkPDFGraphicState(paint));
11109e900419f232872200a76c64357b105531791c4reed@google.com    CanonicalPaints().push(newEntry);
1124ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    return newEntry.fGraphicState;
1134ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
1144ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
1154ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// static
11677d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.orgSkPDFObject* SkPDFGraphicState::GetInvertFunction() {
11777d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org    // This assumes that canonicalPaintsMutex is held.
11877d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org    static SkPDFStream* invertFunction = NULL;
11977d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org    if (!invertFunction) {
12077d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
12177d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        // a type 2 function, so we use a type 4 function.
1225b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org        SkAutoTUnref<SkPDFArray> domainAndRange(new SkPDFArray);
12377d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        domainAndRange->reserve(2);
1244a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        domainAndRange->appendInt(0);
1254a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        domainAndRange->appendInt(1);
12677d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org
12777d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        static const char psInvert[] = "{1 exch sub}";
1285b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org        SkAutoTUnref<SkMemoryStream> psInvertStream(
1295b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org            new SkMemoryStream(&psInvert, strlen(psInvert), true));
13077d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org
13177d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        invertFunction = new SkPDFStream(psInvertStream.get());
1324a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        invertFunction->insertInt("FunctionType", 4);
13377d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        invertFunction->insert("Domain", domainAndRange.get());
13477d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        invertFunction->insert("Range", domainAndRange.get());
13577d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org    }
13677d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org    return invertFunction;
13777d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org}
13877d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org
13977d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org// static
14009e900419f232872200a76c64357b105531791c4reed@google.comSkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState(
1419d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org        SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) {
142e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    // The practical chances of using the same mask more than once are unlikely
143e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    // enough that it's not worth canonicalizing.
14409e900419f232872200a76c64357b105531791c4reed@google.com    SkAutoMutexAcquire lock(CanonicalPaintsMutex());
145e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
1465b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org    SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask"));
1479d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org    if (sMaskMode == kAlpha_SMaskMode) {
1489d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org        sMaskDict->insertName("S", "Alpha");
1499d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org    } else if (sMaskMode == kLuminosity_SMaskMode) {
1509d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org        sMaskDict->insertName("S", "Luminosity");
1519d2ebe897190c9ea93f3c737440bf5ae891a910bcommit-bot@chromium.org    }
152e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref();
153e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
154e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    SkPDFGraphicState* result = new SkPDFGraphicState;
155e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    result->fPopulated = true;
156e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    result->fSMask = true;
1574a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com    result->insertName("Type", "ExtGState");
158e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    result->insert("SMask", sMaskDict.get());
159e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    result->fResources.push(sMask);
160e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    sMask->ref();
161e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
162e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    if (invert) {
16377d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        SkPDFObject* invertFunction = GetInvertFunction();
16477d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        result->fResources.push(invertFunction);
16577d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        invertFunction->ref();
16677d0944aa6a8155375584e197f8e9613c83a9811vandebo@chromium.org        sMaskDict->insert("TR", new SkPDFObjRef(invertFunction))->unref();
167e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    }
168e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
169e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    return result;
170e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org}
171e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
172e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org// static
17309e900419f232872200a76c64357b105531791c4reed@google.comSkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
17409e900419f232872200a76c64357b105531791c4reed@google.com    SkAutoMutexAcquire lock(CanonicalPaintsMutex());
175e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    static SkPDFGraphicState* noSMaskGS = NULL;
176e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    if (!noSMaskGS) {
177e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org        noSMaskGS = new SkPDFGraphicState;
178e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org        noSMaskGS->fPopulated = true;
179e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org        noSMaskGS->fSMask = true;
1804a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        noSMaskGS->insertName("Type", "ExtGState");
1814a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        noSMaskGS->insertName("SMask", "None");
182e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    }
183e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    noSMaskGS->ref();
184e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    return noSMaskGS;
185e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org}
186e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
187e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org// static
18809e900419f232872200a76c64357b105531791c4reed@google.comint SkPDFGraphicState::Find(const SkPaint& paint) {
1894ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    GSCanonicalEntry search(&paint);
19009e900419f232872200a76c64357b105531791c4reed@google.com    return CanonicalPaints().find(search);
1914ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
1924ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
193e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.orgSkPDFGraphicState::SkPDFGraphicState()
194e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    : fPopulated(false),
195e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org      fSMask(false) {
196e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org}
197e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org
1984ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgSkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint)
1994ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    : fPaint(paint),
200e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org      fPopulated(false),
201e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org      fSMask(false) {
2024ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
2034ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
2044ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// populateDict and operator== have to stay in sync with each other.
2054ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgvoid SkPDFGraphicState::populateDict() {
2064ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    if (!fPopulated) {
2074ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        fPopulated = true;
2084a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertName("Type", "ExtGState");
2094ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
2105b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org        SkAutoTUnref<SkPDFScalar> alpha(
2115b20098a0c3b7d3fe65d8e636bc898fb661f6fa8vandebo@chromium.org            new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF)));
2124ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        insert("CA", alpha.get());
2134ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        insert("ca", alpha.get());
2144ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
215a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch);
216a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch);
217a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch);
218a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch);
2194ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2);
2204a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertInt("LC", fPaint.getStrokeCap());
2214ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
222a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch);
223a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch);
224a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch);
225a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch);
2264ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2);
2274a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertInt("LJ", fPaint.getStrokeJoin());
2284ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
2294a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertScalar("LW", fPaint.getStrokeWidth());
2304a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertScalar("ML", fPaint.getStrokeMiter());
231a9a5a610cd95fcedb790e5b1a815654c46f92e52vandebo@chromium.org        insert("SA", new SkPDFBool(true))->unref();  // Auto stroke adjustment.
23219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
23319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
2348c32f5efcf180adc0cbf8ad3a7cac691eba42f20vandebo@chromium.org        // If asMode fails, default to kSrcOver_Mode.
23519caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        if (fPaint.getXfermode())
23619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org            fPaint.getXfermode()->asMode(&xfermode);
23719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        // If we don't support the mode, just use kSrcOver_Mode.
23819caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        if (xfermode < 0 || xfermode > SkXfermode::kLastMode ||
239e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org                blend_mode_from_xfermode(xfermode) == NULL) {
24019caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org            xfermode = SkXfermode::kSrcOver_Mode;
2418c32f5efcf180adc0cbf8ad3a7cac691eba42f20vandebo@chromium.org            NOT_IMPLEMENTED("unsupported xfermode", false);
24219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        }
2434a4ebbe3a50777da8ea52b622d19033fcbe22946reed@google.com        insertName("BM", blend_mode_from_xfermode(xfermode));
2444ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    }
2454ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
2464ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org
2474ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// We're only interested in some fields of the SkPaint, so we have a custom
2484ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org// operator== function.
2494ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.orgbool SkPDFGraphicState::GSCanonicalEntry::operator==(
2504ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org        const SkPDFGraphicState::GSCanonicalEntry& gs) const {
2514ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    const SkPaint* a = fPaint;
2524ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    const SkPaint* b = gs.fPaint;
2534ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    SkASSERT(a != NULL);
2544ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org    SkASSERT(b != NULL);
25519caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
25619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    if (SkColorGetA(a->getColor()) != SkColorGetA(b->getColor()) ||
25719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org           a->getStrokeCap() != b->getStrokeCap() ||
25819caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org           a->getStrokeJoin() != b->getStrokeJoin() ||
25919caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org           a->getStrokeWidth() != b->getStrokeWidth() ||
26019caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org           a->getStrokeMiter() != b->getStrokeMiter()) {
26119caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org        return false;
26219caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    }
26319caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
26419caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode;
2656d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    SkXfermode* aXfermode = a->getXfermode();
2666d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    if (aXfermode) {
2676d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org        aXfermode->asMode(&aXfermodeName);
2686d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    }
2696d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
270e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org            blend_mode_from_xfermode(aXfermodeName) == NULL) {
2716d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org        aXfermodeName = SkXfermode::kSrcOver_Mode;
2726d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    }
273e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    const char* aXfermodeString = blend_mode_from_xfermode(aXfermodeName);
2746d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    SkASSERT(aXfermodeString != NULL);
2756d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org
27619caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org    SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
2776d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    SkXfermode* bXfermode = b->getXfermode();
2786d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    if (bXfermode) {
2796d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org        bXfermode->asMode(&bXfermodeName);
2806d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    }
2816d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
282e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org            blend_mode_from_xfermode(bXfermodeName) == NULL) {
2836d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org        bXfermodeName = SkXfermode::kSrcOver_Mode;
2846d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    }
285e432d6e672ecd3447e82137e6582a99d7bb9407bvandebo@chromium.org    const char* bXfermodeString = blend_mode_from_xfermode(bXfermodeName);
2866d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    SkASSERT(bXfermodeString != NULL);
28719caab4ade022f5f4e876e162330e4ea95f2bd28vandebo@chromium.org
2886d7c64d5630e67e282536f1e79dccffca02e7450vandebo@chromium.org    return strcmp(aXfermodeString, bXfermodeString) == 0;
2894ed46bdbcb3152b1ca2265e2720b8a4051f4ea63vandebo@chromium.org}
290