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