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