180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPDFCatalog.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPDFTypes.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_BUILD_FOR_WIN
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SNPRINTF    _snprintf
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SNPRINTF    snprintf
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFArray)
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFBool)
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFDict)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFInt)
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFName)
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFObject)
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFObjRef)
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFScalar)
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkPDFString)
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObject::emit(SkWStream* stream, SkPDFCatalog* catalog,
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       bool indirect) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPDFObject* realObject = catalog->getSubstituteObject(this);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return realObject->emitObject(stream, catalog, indirect);
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDynamicMemoryWStream buffer;
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    emit(&buffer, catalog, indirect);
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return buffer.getOffset();
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {}
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    catalog->emitObjectNumber(stream, this);
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText(" obj\n");
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    emit(stream, catalog, false);
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText("\nendobj\n");
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFObject::getIndirectOutputSize(SkPDFCatalog* catalog) {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return catalog->getObjectNumberSize(this) + strlen(" obj\n") +
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->getOutputSize(catalog, false) + strlen("\nendobj\n");
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObject::AddResourceHelper(SkPDFObject* resource,
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    SkTDArray<SkPDFObject*>* list) {
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    list->push(resource);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    resource->ref();
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObject::GetResourcesHelper(SkTDArray<SkPDFObject*>* resources,
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     SkTDArray<SkPDFObject*>* result) {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (resources->count()) {
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result->setReserve(result->count() + resources->count());
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < resources->count(); i++) {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result->push((*resources)[i]);
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (*resources)[i]->ref();
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (*resources)[i]->getResources(result);
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerSkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {
77d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkSafeRef(obj);
78d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
79d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFObjRef::~SkPDFObjRef() {}
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             bool indirect) {
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    catalog->emitObjectNumber(stream, fObj.get());
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText(" R");
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFObjRef::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return catalog->getObjectNumberSize(fObj.get()) + strlen(" R");
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFInt::~SkPDFInt() {}
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          bool indirect) {
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return emitIndirectObject(stream, catalog);
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeDecAsText(fValue);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFBool::SkPDFBool(bool value) : fValue(value) {}
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFBool::~SkPDFBool() {}
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          bool indirect) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fValue) {
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeText("true");
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeText("false");
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFBool::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fValue) {
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return strlen("true");
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return strlen("false");
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFScalar::~SkPDFScalar() {}
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             bool indirect) {
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return emitIndirectObject(stream, catalog);
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Append(fValue, stream);
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// static
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // When using floats that are outside the whole value range, we can use
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // integers instead.
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_SCALAR_IS_FIXED)
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeScalarAsText(value);
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif  // SK_SCALAR_IS_FIXED
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value > 32767 || value < -32767) {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeDecAsText(SkScalarRound(value));
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[SkStrAppendScalar_MaxSize];
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->write(buffer, end - buffer);
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return;
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif  // !SK_ALLOW_LARGE_PDF_SCALARS
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_SCALAR_IS_FLOAT) && defined(SK_ALLOW_LARGE_PDF_SCALARS)
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Floats have 24bits of significance, so anything outside that range is
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // no more precise than an int. (Plus PDF doesn't support scientific
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // notation, so this clamps to SK_Max/MinS32).
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value > (1 << 24) || value < -(1 << 24)) {
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeDecAsText(value);
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Continue to enforce the PDF limits for small floats.
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value < 1.0f/65536 && value > -1.0f/65536) {
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeDecAsText(0);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // SkStrAppendFloat might still use scientific notation, so use snprintf
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // directly..
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int kFloat_MaxSize = 19;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[kFloat_MaxSize];
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // %f always prints trailing 0s, so strip them.
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (; buffer[len - 1] == '0' && len > 0; len--) {
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer[len - 1] = '\0';
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (buffer[len - 1] == '.') {
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer[len - 1] = '\0';
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText(buffer);
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return;
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif  // SK_SCALAR_IS_FLOAT && SK_ALLOW_LARGE_PDF_SCALARS
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFString::SkPDFString(const char value[])
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fValue(FormatString(value, strlen(value))) {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFString::SkPDFString(const SkString& value)
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fValue(FormatString(value.c_str(), value.size())) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars)
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fValue(FormatString(value, len, wideChars)) {
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFString::~SkPDFString() {}
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             bool indirect) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect)
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return emitIndirectObject(stream, catalog);
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->write(fValue.c_str(), fValue.size());
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFString::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect)
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return getIndirectOutputSize(catalog);
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fValue.size();
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// static
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString SkPDFString::FormatString(const char* input, size_t len) {
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return DoFormatString(input, len, false, false);
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString SkPDFString::FormatString(const uint16_t* input, size_t len,
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   bool wideChars) {
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return DoFormatString(input, len, true, wideChars);
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// static
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString SkPDFString::DoFormatString(const void* input, size_t len,
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     bool wideInput, bool wideOutput) {
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(len <= kMaxLen);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint16_t* win = (const uint16_t*) input;
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* cin = (const char*) input;
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (wideOutput) {
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(wideInput);
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString result;
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append("<");
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (size_t i = 0; i < len; i++) {
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.appendHex(win[i], 4);
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append(">");
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return result;
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // 7-bit clean is a heuristic to decide what string format to use;
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // a 7-bit clean string should require little escaping.
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool sevenBitClean = true;
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (size_t i = 0; i < len; i++) {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(!wideInput || !(win[i] & ~0xFF));
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char val = wideInput ? win[i] : cin[i];
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (val > '~' || val < ' ') {
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sevenBitClean = false;
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString result;
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sevenBitClean) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append("(");
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (size_t i = 0; i < len; i++) {
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(!wideInput || !(win[i] & ~0xFF));
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            char val = wideInput ? win[i] : cin[i];
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (val == '\\' || val == '(' || val == ')') {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                result.append("\\");
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.append(&val, 1);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append(")");
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append("<");
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (size_t i = 0; i < len; i++) {
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(!wideInput || !(win[i] & ~0xFF));
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned char val = wideInput ? win[i] : cin[i];
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.appendHex(val, 2);
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result.append(">");
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {}
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {}
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFName::~SkPDFName() {}
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPDFName::operator==(const SkPDFName& b) const {
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fValue == b.fValue;
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           bool indirect) {
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->write(fValue.c_str(), fValue.size());
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFName::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(!indirect);
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fValue.size();
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// static
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString SkPDFName::FormatName(const SkString& input) {
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(input.size() <= kMaxLen);
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // TODO(vandebo) If more escaping is needed, improve the linear scan.
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char escaped[] = "#/%()<>[]{}";
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString result("/");
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (size_t i = 0; i < input.size(); i++) {
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (input[i] & 0x80 || input[i] < '!' || strchr(escaped, input[i])) {
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.append("#");
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Mask with 0xFF to avoid sign extension. i.e. #FFFFFF81
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.appendHex(input[i] & 0xFF, 2);
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            result.append(input.c_str() + i, 1);
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFArray::SkPDFArray() {}
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFArray::~SkPDFArray() {
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.unrefAll();
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            bool indirect) {
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return emitIndirectObject(stream, catalog);
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText("[");
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fValue.count(); i++) {
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fValue[i]->emit(stream, catalog, false);
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (i + 1 < fValue.count()) {
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            stream->writeText(" ");
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText("]");
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFArray::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return getIndirectOutputSize(catalog);
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t result = strlen("[]");
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fValue.count()) {
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result += fValue.count() - 1;
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fValue.count(); i++) {
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result += fValue[i]->getOutputSize(catalog, false);
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFArray::reserve(int length) {
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(length <= kMaxLen);
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.setReserve(length);
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) {
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(offset < fValue.count());
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value->ref();
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue[offset]->unref();
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue[offset] = value;
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return value;
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFObject* SkPDFArray::append(SkPDFObject* value) {
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fValue.count() < kMaxLen);
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value->ref();
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.push(value);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return value;
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFArray::appendInt(int32_t value) {
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fValue.count() < kMaxLen);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.push(new SkPDFInt(value));
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFArray::appendScalar(SkScalar value) {
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fValue.count() < kMaxLen);
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.push(new SkPDFScalar(value));
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFArray::appendName(const char name[]) {
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fValue.count() < kMaxLen);
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.push(new SkPDFName(name));
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFDict::SkPDFDict() {}
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFDict::SkPDFDict(const char type[]) {
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    insertName("Type", type);
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFDict::~SkPDFDict() {
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    clear();
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           bool indirect) {
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return emitIndirectObject(stream, catalog);
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText("<<");
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fValue.count(); i++) {
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fValue[i].key->emitObject(stream, catalog, false);
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeText(" ");
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fValue[i].value->emit(stream, catalog, false);
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        stream->writeText("\n");
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stream->writeText(">>");
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkPDFDict::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (indirect) {
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return getIndirectOutputSize(catalog);
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t result = strlen("<<>>") + (fValue.count() * 2);
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fValue.count(); i++) {
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result += fValue[i].key->getOutputSize(catalog, false);
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result += fValue[i].value->getOutputSize(catalog, false);
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) {
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    key->ref();
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value->ref();
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec* newEntry = fValue.append();
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->key = key;
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->value = value;
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return value;
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) {
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value->ref();
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec* newEntry = fValue.append();
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->key = new SkPDFName(key);
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->value = value;
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return value;
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFDict::insertInt(const char key[], int32_t value) {
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec* newEntry = fValue.append();
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->key = new SkPDFName(key);
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->value = new SkPDFInt(value);
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFDict::insertScalar(const char key[], SkScalar value) {
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec* newEntry = fValue.append();
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->key = new SkPDFName(key);
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->value = new SkPDFScalar(value);
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFDict::insertName(const char key[], const char name[]) {
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Rec* newEntry = fValue.append();
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->key = new SkPDFName(key);
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    newEntry->value = new SkPDFName(name);
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPDFDict::clear() {
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fValue.count(); i++) {
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fValue[i].key->unref();
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fValue[i].value->unref();
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fValue.reset();
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFDict::Iter::Iter(const SkPDFDict& dict)
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fIter(dict.fValue.begin()),
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      fStop(dict.fValue.end()) {
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPDFName* SkPDFDict::Iter::next(SkPDFObject** value) {
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fIter != fStop) {
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Rec* cur = fIter;
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fIter++;
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *value = cur->value;
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return cur->key;
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *value = NULL;
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
494