blob: 73f765d3c73092d8bd543c2e39dc59ab3fbc7b45 [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
edisonn@google.com571c70b2013-07-10 17:09:50 +00007
edisonn@google.com3aa35552013-08-14 18:26:20 +00008#include "SkPdfNativeObject.h"
edisonn@google.com33f11b62013-08-14 21:35:27 +00009
10// TODO(edisonn): mac builder does not find the header ... but from headers is ok
11//#include "SkPdfStreamCommonDictionary_autogen.h"
12#include "SkPdfHeaders_autogen.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000013
14#include "SkFlate.h"
15#include "SkStream.h"
16#include "SkPdfNativeTokenizer.h"
17
edisonn@google.comb0145ce2013-08-05 16:23:23 +000018#include "SkBitmap.h"
19#include "SkPdfFont.h"
20
edisonn@google.comaf54a512013-09-13 19:33:42 +000021#include "SkPdfReporter.h"
22
edisonn@google.combca421b2013-09-05 20:00:21 +000023SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull(PUT_TRACK_PARAMETERS_SRC0);
edisonn@google.com571c70b2013-07-10 17:09:50 +000024
edisonn@google.com3aa35552013-08-14 18:26:20 +000025bool SkPdfNativeObject::applyFlateDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000026 if (!SkFlate::HaveFlate()) {
edisonn@google.comaf54a512013-09-13 19:33:42 +000027 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNoFlateLibrary_SkPdfIssue, "forgot to link with flate library?", NULL, NULL);
edisonn@google.com571c70b2013-07-10 17:09:50 +000028 return false;
29 }
30
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000031 const unsigned char* old = fStr.fBuffer;
32 bool deleteOld = isStreamOwned();
33
34 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
edisonn@google.com571c70b2013-07-10 17:09:50 +000035 SkDynamicMemoryWStream uncompressedData;
36
37 if (SkFlate::Inflate(&skstream, &uncompressedData)) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000038 fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit + kUnfilteredStreamBit;
39 fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
40 uncompressedData.copyTo((void*)fStr.fBuffer);
41
42 if (deleteOld) {
43 delete[] old;
44 }
45
edisonn@google.com571c70b2013-07-10 17:09:50 +000046 return true;
47 } else {
edisonn@google.comaf54a512013-09-13 19:33:42 +000048 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL);
edisonn@google.com571c70b2013-07-10 17:09:50 +000049 return false;
50 }
51}
52
edisonn@google.com3aa35552013-08-14 18:26:20 +000053bool SkPdfNativeObject::applyDCTDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000054 // this would fail, and it won't allow any more filters.
55 // technically, it would be possible, but not a real world scenario
56 // TODO(edisonn): or get the image here and store it for fast retrieval?
57 return false;
58}
59
edisonn@google.com3aa35552013-08-14 18:26:20 +000060bool SkPdfNativeObject::applyFilter(const char* name) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000061 if (strcmp(name, "FlateDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000062 return applyFlateDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000063 } else if (strcmp(name, "DCTDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000064 return applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000065 }
edisonn@google.comaf54a512013-09-13 19:33:42 +000066 SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this, NULL);
edisonn@google.com571c70b2013-07-10 17:09:50 +000067 return false;
68}
69
edisonn@google.com3aa35552013-08-14 18:26:20 +000070bool SkPdfNativeObject::filterStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +000071 SkPdfMarkObjectUsed();
72
edisonn@google.com571c70b2013-07-10 17:09:50 +000073 if (!hasStream()) {
edisonn@google.comaf54a512013-09-13 19:33:42 +000074 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this, NULL);
edisonn@google.com571c70b2013-07-10 17:09:50 +000075 return false;
76 }
77
78 if (isStreamFiltered()) {
79 return true;
80 }
81
82 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
83
84 if (!stream->has_Filter()) {
85 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000086 } else if (stream->isFilterAName(NULL)) {
edisonn@google.com063d7072013-08-16 15:05:08 +000087 SkString filterName = stream->getFilterAsName(NULL);
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000088 applyFilter(filterName.c_str());
edisonn@google.com571c70b2013-07-10 17:09:50 +000089 } else if (stream->isFilterAArray(NULL)) {
90 const SkPdfArray* filters = stream->getFilterAsArray(NULL);
91 int cnt = filters->size();
92 for (int i = cnt - 1; i >= 0; i--) {
edisonn@google.com3aa35552013-08-14 18:26:20 +000093 const SkPdfNativeObject* filterName = filters->objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +000094 if (filterName != NULL && filterName->isName()) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000095 if (!applyFilter(filterName->nameValue())) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000096 break;
97 }
98 } else {
edisonn@google.comaf54a512013-09-13 19:33:42 +000099 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue, "filter name should be a Name", this, NULL);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000100 }
101 }
102 }
103
edisonn@google.com571c70b2013-07-10 17:09:50 +0000104 return true;
105}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000106
edisonn@google.com3aa35552013-08-14 18:26:20 +0000107void SkPdfNativeObject::releaseData() {
edisonn@google.comaf54a512013-09-13 19:33:42 +0000108#ifdef PDF_TRACK_OBJECT_USAGE
109 SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, NULL, this, "Unused object in rendering");
110#endif // PDF_TRACK_OBJECT_USAGE
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000111
112 SkPdfMarkObjectUnused();
113
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000114 if (fData) {
115 switch (fDataType) {
116 case kFont_Data:
117 delete (SkPdfFont*)fData;
118 break;
119 case kBitmap_Data:
120 delete (SkBitmap*)fData;
121 break;
122 default:
123 SkASSERT(false);
124 break;
125 }
126 }
127 fData = NULL;
128 fDataType = kEmpty_Data;
129}