1/* 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 */ 7 8#include "SkPdfNativeObject.h" 9 10#include "SkBitmap.h" 11#include "SkFlate.h" 12#include "SkPdfFont.h" 13#include "SkPdfNativeTokenizer.h" 14#include "SkPdfReporter.h" 15#include "SkStream.h" 16 17// TODO(edisonn): mac builder does not find the header ... but from headers is ok 18//#include "SkPdfStreamCommonDictionary_autogen.h" 19#include "SkPdfHeaders_autogen.h" 20 21 22SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull(); 23 24bool SkPdfNativeObject::applyFlateDecodeFilter() { 25 const unsigned char* old = fStr.fBuffer; 26 bool deleteOld = isStreamOwned(); 27 28 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false); 29 SkDynamicMemoryWStream uncompressedData; 30 31 if (SkFlate::Inflate(&skstream, &uncompressedData)) { 32 fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit + 33 kUnfilteredStreamBit; 34 fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()]; 35 uncompressedData.copyTo((void*)fStr.fBuffer); 36 37 if (deleteOld) { 38 delete[] old; 39 } 40 41 return true; 42 } else { 43 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL); 44 return false; 45 } 46} 47 48bool SkPdfNativeObject::applyDCTDecodeFilter() { 49 // applyDCTDecodeFilter will fail, and it won't allow any more filters. 50 // technically, it would be possible, but not a real world scenario. 51 // in this way we create the image from the DCT stream directly. 52 return false; 53} 54 55bool SkPdfNativeObject::applyFilter(const char* name) { 56 if (strcmp(name, "FlateDecode") == 0) { 57 return applyFlateDecodeFilter(); 58 } else if (strcmp(name, "DCTDecode") == 0) { 59 return applyDCTDecodeFilter(); 60 } 61 SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this, 62 NULL); 63 return false; 64} 65 66bool SkPdfNativeObject::filterStream() { 67 SkPdfMarkObjectUsed(); 68 69 if (!hasStream()) { 70 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this, 71 NULL); 72 return false; 73 } 74 75 if (isStreamFiltered()) { 76 return true; 77 } 78 79 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this; 80 81 if (!stream->has_Filter()) { 82 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit; 83 } else if (stream->isFilterAName(NULL)) { 84 SkString filterName = stream->getFilterAsName(NULL); 85 applyFilter(filterName.c_str()); 86 } else if (stream->isFilterAArray(NULL)) { 87 const SkPdfArray* filters = stream->getFilterAsArray(NULL); 88 int cnt = (int) filters->size(); 89 for (int i = cnt - 1; i >= 0; i--) { 90 const SkPdfNativeObject* filterName = filters->objAtAIndex(i); 91 if (filterName != NULL && filterName->isName()) { 92 if (!applyFilter(filterName->nameValue())) { 93 break; 94 } 95 } else { 96 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue, 97 "filter name should be a Name", this, NULL); 98 } 99 } 100 } 101 102 return true; 103} 104 105void SkPdfNativeObject::releaseData() { 106#ifdef PDF_TRACK_OBJECT_USAGE 107 SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, kUnusedObject_SkPdfIssue, 108 "Unused object in rendering", this, NULL); 109#endif // PDF_TRACK_OBJECT_USAGE 110 111 SkPdfMarkObjectUnused(); 112 113 if (fData) { 114 switch (fDataType) { 115 case kFont_Data: 116 delete (SkPdfFont*)fData; 117 break; 118 case kBitmap_Data: 119 delete (SkBitmap*)fData; 120 break; 121 default: 122 SkASSERT(false); 123 break; 124 } 125 } 126 fData = NULL; 127 fDataType = kEmpty_Data; 128} 129