blob: 5a1a6ca8224a38e72a69e6f688e03b857819aa06 [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.com3aa35552013-08-14 18:26:20 +000021SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull();
edisonn@google.com571c70b2013-07-10 17:09:50 +000022
edisonn@google.com3aa35552013-08-14 18:26:20 +000023bool SkPdfNativeObject::applyFlateDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000024 if (!SkFlate::HaveFlate()) {
25 // TODO(edisonn): warn, make callers handle it
26 return false;
27 }
28
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000029 const unsigned char* old = fStr.fBuffer;
30 bool deleteOld = isStreamOwned();
31
32 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
edisonn@google.com571c70b2013-07-10 17:09:50 +000033 SkDynamicMemoryWStream uncompressedData;
34
35 if (SkFlate::Inflate(&skstream, &uncompressedData)) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000036 fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit + kUnfilteredStreamBit;
37 fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
38 uncompressedData.copyTo((void*)fStr.fBuffer);
39
40 if (deleteOld) {
41 delete[] old;
42 }
43
edisonn@google.com571c70b2013-07-10 17:09:50 +000044 return true;
45 } else {
46 // TODO(edisonn): warn, make callers handle it
47 return false;
48 }
49}
50
edisonn@google.com3aa35552013-08-14 18:26:20 +000051bool SkPdfNativeObject::applyDCTDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000052 // this would fail, and it won't allow any more filters.
53 // technically, it would be possible, but not a real world scenario
54 // TODO(edisonn): or get the image here and store it for fast retrieval?
55 return false;
56}
57
edisonn@google.com3aa35552013-08-14 18:26:20 +000058bool SkPdfNativeObject::applyFilter(const char* name) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000059 if (strcmp(name, "FlateDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000060 return applyFlateDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000061 } else if (strcmp(name, "DCTDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000062 return applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000063 }
64 // TODO(edisonn): allert, not supported, but should be implemented asap
65 return false;
66}
67
edisonn@google.com3aa35552013-08-14 18:26:20 +000068bool SkPdfNativeObject::filterStream() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000069 if (!hasStream()) {
70 return false;
71 }
72
73 if (isStreamFiltered()) {
74 return true;
75 }
76
77 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
78
79 if (!stream->has_Filter()) {
80 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000081 } else if (stream->isFilterAName(NULL)) {
edisonn@google.com063d7072013-08-16 15:05:08 +000082 SkString filterName = stream->getFilterAsName(NULL);
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000083 applyFilter(filterName.c_str());
edisonn@google.com571c70b2013-07-10 17:09:50 +000084 } else if (stream->isFilterAArray(NULL)) {
85 const SkPdfArray* filters = stream->getFilterAsArray(NULL);
86 int cnt = filters->size();
87 for (int i = cnt - 1; i >= 0; i--) {
edisonn@google.com3aa35552013-08-14 18:26:20 +000088 const SkPdfNativeObject* filterName = filters->objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +000089 if (filterName != NULL && filterName->isName()) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000090 if (!applyFilter(filterName->nameValue())) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000091 break;
92 }
93 } else {
94 // TODO(edisonn): report warning
95 }
96 }
97 }
98
edisonn@google.com571c70b2013-07-10 17:09:50 +000099 return true;
100}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000101
edisonn@google.com3aa35552013-08-14 18:26:20 +0000102void SkPdfNativeObject::releaseData() {
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000103 if (fData) {
104 switch (fDataType) {
105 case kFont_Data:
106 delete (SkPdfFont*)fData;
107 break;
108 case kBitmap_Data:
109 delete (SkBitmap*)fData;
110 break;
111 default:
112 SkASSERT(false);
113 break;
114 }
115 }
116 fData = NULL;
117 fDataType = kEmpty_Data;
118}