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