OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkPDFTypes.h" | 9 #include "SkPDFTypes.h" |
10 #include "SkPDFUtils.h" | 10 #include "SkPDFUtils.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 while (*n) { | 92 while (*n) { |
93 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) { | 93 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) { |
94 return false; | 94 return false; |
95 } | 95 } |
96 ++n; | 96 ++n; |
97 } | 97 } |
98 return true; | 98 return true; |
99 } | 99 } |
100 #endif // SK_DEBUG | 100 #endif // SK_DEBUG |
101 | 101 |
102 // Given an arbitrary string, convert it to a valid name. | 102 // Given an arbitrary string, write it as a valid name (not including |
103 static SkString escape_name(const char* name, size_t len) { | 103 // leading slash). |
| 104 static void write_name_escaped(SkWStream* o, const char* name) { |
104 static const char kToEscape[] = "#/%()<>[]{}"; | 105 static const char kToEscape[] = "#/%()<>[]{}"; |
105 int count = 0; | 106 static const char kHex[] = "0123456789ABCDEF"; |
106 const char* const end = &name[len]; | 107 for (const uint8_t* n = reinterpret_cast<const uint8_t*>(name); *n; ++n) { |
107 for (const char* n = name; n != end; ++n) { | |
108 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { | 108 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { |
109 count += 2; | 109 char buffer[3] = {'#', '\0', '\0'}; |
110 } | 110 buffer[1] = kHex[(*n >> 4) & 0xF]; |
111 ++count; | 111 buffer[2] = kHex[*n & 0xF]; |
112 } | 112 o->write(buffer, sizeof(buffer)); |
113 SkString result(count); | |
114 char* s = result.writable_str(); | |
115 static const char kHex[] = "0123456789ABCDEF"; | |
116 for (const char* n = name; n != end; ++n) { | |
117 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { | |
118 *s++ = '#'; | |
119 *s++ = kHex[(*n >> 4) & 0xF]; | |
120 *s++ = kHex[*n & 0xF]; | |
121 } else { | 113 } else { |
122 *s++ = *n; | 114 o->write(n, 1); |
123 } | 115 } |
124 } | 116 } |
125 SkASSERT(&result.writable_str()[count] == s); // don't over-write | |
126 return result; // allocated space | |
127 } | |
128 | |
129 static SkString escape_name(const SkString& name) { | |
130 return escape_name(name.c_str(), name.size()); | |
131 } | 117 } |
132 | 118 |
133 static void write_string(SkWStream* o, const SkString& s) { | 119 static void write_string(SkWStream* o, const SkString& s) { |
134 o->write(s.c_str(), s.size()); | 120 o->write(s.c_str(), s.size()); |
135 } | 121 } |
136 | 122 |
137 static SkString format_string(const SkString& s) { | 123 static SkString format_string(const SkString& s) { |
138 return SkPDFUtils::FormatString(s.c_str(), s.size()); | 124 return SkPDFUtils::FormatString(s.c_str(), s.size()); |
139 } | 125 } |
140 | 126 |
(...skipping 18 matching lines...) Expand all Loading... |
159 stream->writeText("/"); | 145 stream->writeText("/"); |
160 SkASSERT(is_valid_name(fStaticString)); | 146 SkASSERT(is_valid_name(fStaticString)); |
161 stream->writeText(fStaticString); | 147 stream->writeText(fStaticString); |
162 return; | 148 return; |
163 case Type::kString: | 149 case Type::kString: |
164 SkASSERT(fStaticString); | 150 SkASSERT(fStaticString); |
165 write_string(stream, format_string(fStaticString)); | 151 write_string(stream, format_string(fStaticString)); |
166 return; | 152 return; |
167 case Type::kNameSkS: | 153 case Type::kNameSkS: |
168 stream->writeText("/"); | 154 stream->writeText("/"); |
169 write_string(stream, escape_name(*pun(fSkString))); | 155 write_name_escaped(stream, pun(fSkString)->c_str()); |
170 return; | 156 return; |
171 case Type::kStringSkS: | 157 case Type::kStringSkS: |
172 write_string(stream, format_string(*pun(fSkString))); | 158 write_string(stream, format_string(*pun(fSkString))); |
173 return; | 159 return; |
174 case Type::kObjRef: | 160 case Type::kObjRef: |
175 stream->writeDecAsText(objNumMap.getObjectNumber( | 161 stream->writeDecAsText(objNumMap.getObjectNumber( |
176 substitutes.getSubstitute(fObject))); | 162 substitutes.getSubstitute(fObject))); |
177 stream->writeText(" 0 R"); // Generation number is always 0. | 163 stream->writeText(" 0 R"); // Generation number is always 0. |
178 return; | 164 return; |
179 case Type::kObject: | 165 case Type::kObject: |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 fObjects.push(obj); | 466 fObjects.push(obj); |
481 return true; | 467 return true; |
482 } | 468 } |
483 | 469 |
484 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { | 470 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { |
485 int32_t* objectNumberFound = fObjectNumbers.find(obj); | 471 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
486 SkASSERT(objectNumberFound); | 472 SkASSERT(objectNumberFound); |
487 return *objectNumberFound; | 473 return *objectNumberFound; |
488 } | 474 } |
489 | 475 |
OLD | NEW |