1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com/*
2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Copyright 2013 Google Inc.
3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com *
4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Use of this source code is governed by a BSD-style license that can be
5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * found in the LICENSE file.
6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com */
7571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
83aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com#include "SkPdfNativeObject.h"
933f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com
10c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkBitmap.h"
11571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include "SkFlate.h"
12c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfFont.h"
13571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include "SkPdfNativeTokenizer.h"
14c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfReporter.h"
15c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkStream.h"
16571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
17c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com// TODO(edisonn): mac builder does not find the header ... but from headers is ok
18c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com//#include "SkPdfStreamCommonDictionary_autogen.h"
19c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfHeaders_autogen.h"
20b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com
21af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com
22598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.comSkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull();
23571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
243aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.combool SkPdfNativeObject::applyFlateDecodeFilter() {
25571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (!SkFlate::HaveFlate()) {
26c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNoFlateLibrary_SkPdfIssue,
27c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                    "forgot to link with flate library?", NULL, NULL);
28571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        return false;
29571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
30571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
312ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com    const unsigned char* old = fStr.fBuffer;
322ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com    bool deleteOld = isStreamOwned();
332ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com
342ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com    SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
35571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    SkDynamicMemoryWStream uncompressedData;
36571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
37571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (SkFlate::Inflate(&skstream, &uncompressedData)) {
38c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com        fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit +
39c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                      kUnfilteredStreamBit;
402ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
412ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        uncompressedData.copyTo((void*)fStr.fBuffer);
422ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com
432ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        if (deleteOld) {
442ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com            delete[] old;
452ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        }
462ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com
47571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        return true;
48571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    } else {
49af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL);
50571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        return false;
51571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
52571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com}
53571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
543aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.combool SkPdfNativeObject::applyDCTDecodeFilter() {
55c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com    // applyDCTDecodeFilter will fail, and it won't allow any more filters.
56c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com    // technically, it would be possible, but not a real world scenario.
57c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com    // in this way we create the image from the DCT stream directly.
58571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    return false;
59571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com}
60571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
613aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.combool SkPdfNativeObject::applyFilter(const char* name) {
62571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (strcmp(name, "FlateDecode") == 0) {
632ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        return applyFlateDecodeFilter();
64571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    } else if (strcmp(name, "DCTDecode") == 0) {
652ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        return applyDCTDecodeFilter();
66571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
67c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com    SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this,
68c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                NULL);
69571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    return false;
70571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com}
71571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
723aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.combool SkPdfNativeObject::filterStream() {
730fd25d8b22ae092183f3dc67dec4c0c1bbde06bfedisonn@google.com    SkPdfMarkObjectUsed();
740fd25d8b22ae092183f3dc67dec4c0c1bbde06bfedisonn@google.com
75571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (!hasStream()) {
76c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com        SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this,
77c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                    NULL);
78571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        return false;
79571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
80571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
81571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (isStreamFiltered()) {
82571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        return true;
83571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
84571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
85571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
86571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
87571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    if (!stream->has_Filter()) {
88571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
892ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com    } else if (stream->isFilterAName(NULL)) {
90063d7072ef45971c17045721626b3f0cd052b3b9edisonn@google.com        SkString filterName = stream->getFilterAsName(NULL);
912ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com        applyFilter(filterName.c_str());
92571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    } else if (stream->isFilterAArray(NULL)) {
93571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        const SkPdfArray* filters = stream->getFilterAsArray(NULL);
945f008652f69ce7809b920b9fa573bc72216acd51scroggo@google.com        int cnt = (int) filters->size();
95571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        for (int i = cnt - 1; i >= 0; i--) {
963aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com            const SkPdfNativeObject* filterName = filters->objAtAIndex(i);
97571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com            if (filterName != NULL && filterName->isName()) {
982ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com                if (!applyFilter(filterName->nameValue())) {
99571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com                    break;
100571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com                }
101571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com            } else {
102c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue,
103c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                            "filter name should be a Name", this, NULL);
104571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com            }
105571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com        }
106571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    }
107571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com
108571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com    return true;
109571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com}
110b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com
1113aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comvoid SkPdfNativeObject::releaseData() {
112af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com#ifdef PDF_TRACK_OBJECT_USAGE
1137d8013f3064cd202f5a2344a1ab1860fd7511bb3scroggo@google.com    SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, kUnusedObject_SkPdfIssue,
114c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com                  "Unused object in rendering", this, NULL);
115af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com#endif  // PDF_TRACK_OBJECT_USAGE
1160fd25d8b22ae092183f3dc67dec4c0c1bbde06bfedisonn@google.com
1170fd25d8b22ae092183f3dc67dec4c0c1bbde06bfedisonn@google.com    SkPdfMarkObjectUnused();
1180fd25d8b22ae092183f3dc67dec4c0c1bbde06bfedisonn@google.com
119b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com    if (fData) {
120b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com        switch (fDataType) {
121b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com            case kFont_Data:
122b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                delete (SkPdfFont*)fData;
123b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                break;
124b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com            case kBitmap_Data:
125b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                delete (SkBitmap*)fData;
126b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                break;
127b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com            default:
128b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                SkASSERT(false);
129b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com                break;
130b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com        }
131b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com    }
132b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com    fData = NULL;
133b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com    fDataType = kEmpty_Data;
134b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com}
135