| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkPDFMetadata.h" | 8 #include "SkPDFMetadata.h" |
| 9 #include "SkPDFTypes.h" | 9 #include "SkPDFTypes.h" |
| 10 #include <utility> |
| 10 | 11 |
| 11 #ifdef SK_PDF_GENERATE_PDFA | 12 #ifdef SK_PDF_GENERATE_PDFA |
| 12 #include "SkMD5.h" | 13 #include "SkMD5.h" |
| 13 #endif | 14 #endif |
| 14 | 15 |
| 15 static SkString pdf_date(const SkTime::DateTime& dt) { | 16 static SkString pdf_date(const SkTime::DateTime& dt) { |
| 16 int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes); | 17 int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes); |
| 17 char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-'; | 18 char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-'; |
| 18 int timeZoneHours = SkTAbs(timeZoneMinutes) / 60; | 19 int timeZoneHours = SkTAbs(timeZoneMinutes) / 60; |
| 19 timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60; | 20 timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 length = _vscprintf(format, args); | 111 length = _vscprintf(format, args); |
| 111 va_end(args); | 112 va_end(args); |
| 112 | 113 |
| 113 SkString string((size_t)length); | 114 SkString string((size_t)length); |
| 114 va_start(args, format); | 115 va_start(args, format); |
| 115 SkDEBUGCODE(int check = ) _vsnprintf_s(string.writable_str(), length + 1, | 116 SkDEBUGCODE(int check = ) _vsnprintf_s(string.writable_str(), length + 1, |
| 116 _TRUNCATE, format, args); | 117 _TRUNCATE, format, args); |
| 117 va_end(args); | 118 va_end(args); |
| 118 SkASSERT(check == length); | 119 SkASSERT(check == length); |
| 119 SkASSERT(string[length] == '\0'); | 120 SkASSERT(string[length] == '\0'); |
| 120 return skstd::move(string); | 121 return std::move(string); |
| 121 #else // C99/C++11 standard vsnprintf | 122 #else // C99/C++11 standard vsnprintf |
| 122 // TODO: When all compilers support this, remove windows-specific code. | 123 // TODO: When all compilers support this, remove windows-specific code. |
| 123 va_list args; | 124 va_list args; |
| 124 va_start(args, format); | 125 va_start(args, format); |
| 125 char buffer[1024]; | 126 char buffer[1024]; |
| 126 int length = vsnprintf(buffer, sizeof(buffer), format, args); | 127 int length = vsnprintf(buffer, sizeof(buffer), format, args); |
| 127 va_end(args); | 128 va_end(args); |
| 128 if (length < 0) { | 129 if (length < 0) { |
| 129 return SkString(); | 130 return SkString(); |
| 130 } | 131 } |
| 131 if (length < (int)sizeof(buffer)) { | 132 if (length < (int)sizeof(buffer)) { |
| 132 return SkString(buffer, length); | 133 return SkString(buffer, length); |
| 133 } | 134 } |
| 134 SkString string((size_t)length); | 135 SkString string((size_t)length); |
| 135 va_start(args, format); | 136 va_start(args, format); |
| 136 SkDEBUGCODE(int check = ) | 137 SkDEBUGCODE(int check = ) |
| 137 vsnprintf(string.writable_str(), length + 1, format, args); | 138 vsnprintf(string.writable_str(), length + 1, format, args); |
| 138 va_end(args); | 139 va_end(args); |
| 139 SkASSERT(check == length); | 140 SkASSERT(check == length); |
| 140 SkASSERT(string[length] == '\0'); | 141 SkASSERT(string[length] == '\0'); |
| 141 return skstd::move(string); | 142 return std::move(string); |
| 142 #endif | 143 #endif |
| 143 } | 144 } |
| 144 | 145 |
| 145 static const SkString get(const SkTArray<SkDocument::Attribute>& info, | 146 static const SkString get(const SkTArray<SkDocument::Attribute>& info, |
| 146 const char* key) { | 147 const char* key) { |
| 147 for (const auto& keyValue : info) { | 148 for (const auto& keyValue : info) { |
| 148 if (keyValue.fKey.equals(key)) { | 149 if (keyValue.fKey.equals(key)) { |
| 149 return keyValue.fValue; | 150 return keyValue.fValue; |
| 150 } | 151 } |
| 151 } | 152 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 178 HEXIFY(data, ptr, gHex, 6); | 179 HEXIFY(data, ptr, gHex, 6); |
| 179 SkASSERT(ptr == buffer + 36); | 180 SkASSERT(ptr == buffer + 36); |
| 180 SkASSERT(data == uuid.fData + 16); | 181 SkASSERT(data == uuid.fData + 16); |
| 181 return SkString(buffer, 36); | 182 return SkString(buffer, 36); |
| 182 } | 183 } |
| 183 #undef HEXIFY | 184 #undef HEXIFY |
| 184 | 185 |
| 185 namespace { | 186 namespace { |
| 186 class PDFXMLObject final : public SkPDFObject { | 187 class PDFXMLObject final : public SkPDFObject { |
| 187 public: | 188 public: |
| 188 PDFXMLObject(SkString xml) : fXML(skstd::move(xml)) {} | 189 PDFXMLObject(SkString xml) : fXML(std::move(xml)) {} |
| 189 void emitObject(SkWStream* stream, | 190 void emitObject(SkWStream* stream, |
| 190 const SkPDFObjNumMap& omap, | 191 const SkPDFObjNumMap& omap, |
| 191 const SkPDFSubstituteMap& smap) const override { | 192 const SkPDFSubstituteMap& smap) const override { |
| 192 SkPDFDict dict("Metadata"); | 193 SkPDFDict dict("Metadata"); |
| 193 dict.insertName("Subtype", "XML"); | 194 dict.insertName("Subtype", "XML"); |
| 194 dict.insertInt("Length", fXML.size()); | 195 dict.insertInt("Length", fXML.size()); |
| 195 dict.emitObject(stream, omap, smap); | 196 dict.emitObject(stream, omap, smap); |
| 196 static const char streamBegin[] = " stream\n"; | 197 static const char streamBegin[] = " stream\n"; |
| 197 stream->write(streamBegin, strlen(streamBegin)); | 198 stream->write(streamBegin, strlen(streamBegin)); |
| 198 // Do not compress this. The standard requires that a | 199 // Do not compress this. The standard requires that a |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 *out++ = input[i]; | 252 *out++ = input[i]; |
| 252 } | 253 } |
| 253 } | 254 } |
| 254 if (after) { | 255 if (after) { |
| 255 strncpy(out, after, afterLen); | 256 strncpy(out, after, afterLen); |
| 256 out += afterLen; | 257 out += afterLen; |
| 257 } | 258 } |
| 258 // Validate that we haven't written outside of our string. | 259 // Validate that we haven't written outside of our string. |
| 259 SkASSERT(out == &output.writable_str()[output.size()]); | 260 SkASSERT(out == &output.writable_str()[output.size()]); |
| 260 *out = '\0'; | 261 *out = '\0'; |
| 261 return skstd::move(output); | 262 return std::move(output); |
| 262 } | 263 } |
| 263 | 264 |
| 264 SkPDFObject* SkPDFMetadata::createXMPObject(const UUID& doc, | 265 SkPDFObject* SkPDFMetadata::createXMPObject(const UUID& doc, |
| 265 const UUID& instance) const { | 266 const UUID& instance) const { |
| 266 static const char templateString[] = | 267 static const char templateString[] = |
| 267 "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" | 268 "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" |
| 268 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"\n" | 269 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"\n" |
| 269 " x:xmptk=\"Adobe XMP Core 5.4-c005 78.147326, " | 270 " x:xmptk=\"Adobe XMP Core 5.4-c005 78.147326, " |
| 270 "2012/08/23-13:03:03\">\n" | 271 "2012/08/23-13:03:03\">\n" |
| 271 "<rdf:RDF " | 272 "<rdf:RDF " |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 SkString instanceID = uuid_to_string(instance); | 342 SkString instanceID = uuid_to_string(instance); |
| 342 SkASSERT(0 == count_xml_escape_size(instanceID)); | 343 SkASSERT(0 == count_xml_escape_size(instanceID)); |
| 343 return new PDFXMLObject(sk_string_printf( | 344 return new PDFXMLObject(sk_string_printf( |
| 344 templateString, modificationDate.c_str(), creationDate.c_str(), | 345 templateString, modificationDate.c_str(), creationDate.c_str(), |
| 345 metadataDate.c_str(), creator.c_str(), title.c_str(), | 346 metadataDate.c_str(), creator.c_str(), title.c_str(), |
| 346 subject.c_str(), author.c_str(), keywords1.c_str(), | 347 subject.c_str(), author.c_str(), keywords1.c_str(), |
| 347 documentID.c_str(), instanceID.c_str(), keywords2.c_str())); | 348 documentID.c_str(), instanceID.c_str(), keywords2.c_str())); |
| 348 } | 349 } |
| 349 | 350 |
| 350 #endif // SK_PDF_GENERATE_PDFA | 351 #endif // SK_PDF_GENERATE_PDFA |
| OLD | NEW |