Home | History | Annotate | Download | only in pdf
      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 "SkPDFResourceDict.h"
      9 #include "SkPostConfig.h"
     10 
     11 // Sanity check that the values of enum SkPDFResourceType correspond to the
     12 // expected values as defined in the arrays below.
     13 // If these are failing, you may need to update the resource_type_prefixes
     14 // and resource_type_names arrays below.
     15 SK_COMPILE_ASSERT(SkPDFResourceDict::kExtGState_ResourceType == 0,
     16                   resource_type_mismatch);
     17 SK_COMPILE_ASSERT(SkPDFResourceDict::kPattern_ResourceType == 1,
     18                   resource_type_mismatch);
     19 SK_COMPILE_ASSERT(SkPDFResourceDict::kXObject_ResourceType == 2,
     20                   resource_type_mismatch);
     21 SK_COMPILE_ASSERT(SkPDFResourceDict::kFont_ResourceType == 3,
     22                   resource_type_mismatch);
     23 
     24 static const char resource_type_prefixes[] = {
     25         'G',
     26         'P',
     27         'X',
     28         'F'
     29 };
     30 
     31 static const char* resource_type_names[] = {
     32         "ExtGState",
     33         "Pattern",
     34         "XObject",
     35         "Font"
     36 };
     37 
     38 static char get_resource_type_prefix(
     39         SkPDFResourceDict::SkPDFResourceType type) {
     40     SkASSERT(type >= 0);
     41     SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);
     42 
     43     return resource_type_prefixes[type];
     44 }
     45 
     46 static const char* get_resource_type_name(
     47         SkPDFResourceDict::SkPDFResourceType type) {
     48     SkASSERT(type >= 0);
     49     SkASSERT(type < SkPDFResourceDict::kResourceTypeCount);
     50 
     51     return resource_type_names[type];
     52 }
     53 
     54 SkPDFResourceDict::SkPDFResourceDict() : SkPDFDict() {
     55     const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
     56     SkPDFArray* procSets = SkNEW(SkPDFArray());
     57 
     58     procSets->reserve(SK_ARRAY_COUNT(procs));
     59     for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++) {
     60         procSets->appendName(procs[i]);
     61     }
     62     insert("ProcSets", procSets)->unref();
     63 
     64     // Actual sub-dicts will be lazily added later
     65     fTypes.setCount(kResourceTypeCount);
     66     for (int i=0; i < kResourceTypeCount; i++) {
     67         fTypes[i] = NULL;
     68     }
     69 }
     70 
     71 SkPDFObject* SkPDFResourceDict::insertResourceAsReference(
     72         SkPDFResourceType type, int key, SkPDFObject* value) {
     73     SkAutoTUnref<SkPDFObjRef> ref(SkNEW_ARGS(SkPDFObjRef, (value)));
     74     insertResource(type, key, ref);
     75     fResources.add(value);
     76 
     77     return value;
     78 }
     79 
     80 void SkPDFResourceDict::getReferencedResources(
     81         const SkTSet<SkPDFObject*>& knownResourceObjects,
     82         SkTSet<SkPDFObject*>* newResourceObjects,
     83         bool recursive) const {
     84     // TODO: reserve not correct if we need to recursively explore.
     85     newResourceObjects->setReserve(newResourceObjects->count() +
     86                                    fResources.count());
     87 
     88     for (int i = 0; i < fResources.count(); i++) {
     89         if (!knownResourceObjects.contains(fResources[i]) &&
     90                 !newResourceObjects->contains(fResources[i])) {
     91             newResourceObjects->add(fResources[i]);
     92             fResources[i]->ref();
     93             if (recursive) {
     94                 fResources[i]->getResources(knownResourceObjects,
     95                                             newResourceObjects);
     96             }
     97         }
     98     }
     99 }
    100 
    101 SkString SkPDFResourceDict::getResourceName(
    102         SkPDFResourceType type, int key) {
    103     SkString keyString;
    104     keyString.printf("%c%d", get_resource_type_prefix(type), key);
    105     return keyString;
    106 }
    107 
    108 SkPDFObject* SkPDFResourceDict::insertResource(
    109         SkPDFResourceType type, int key, SkPDFObject* value) {
    110     SkPDFDict* typeDict = fTypes[type];
    111     if (NULL == typeDict) {
    112         SkAutoTUnref<SkPDFDict> newDict(SkNEW(SkPDFDict()));
    113         SkAutoTUnref<SkPDFName> typeName(
    114                 SkNEW_ARGS(SkPDFName, (get_resource_type_name(type))));
    115         insert(typeName, newDict);  // ref counting handled here
    116         fTypes[type] = newDict;
    117         typeDict = newDict.get();
    118     }
    119 
    120     SkAutoTUnref<SkPDFName> keyName(
    121             SkNEW_ARGS(SkPDFName, (getResourceName(type, key))));
    122     typeDict->insert(keyName, value);
    123     return value;
    124 }
    125