| 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 "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
| 9 #include "SkFlate.h" | 9 #include "SkFlate.h" |
| 10 #include "SkPDFBitmap.h" | 10 #include "SkPDFBitmap.h" |
| 11 #include "SkPDFCanon.h" | 11 #include "SkPDFCanon.h" |
| 12 #include "SkPDFCatalog.h" | |
| 13 #include "SkStream.h" | 12 #include "SkStream.h" |
| 14 #include "SkUnPreMultiply.h" | 13 #include "SkUnPreMultiply.h" |
| 15 | 14 |
| 16 //////////////////////////////////////////////////////////////////////////////// | 15 //////////////////////////////////////////////////////////////////////////////// |
| 17 | 16 |
| 18 static void pdf_stream_begin(SkWStream* stream) { | 17 static void pdf_stream_begin(SkWStream* stream) { |
| 19 static const char streamBegin[] = " stream\n"; | 18 static const char streamBegin[] = " stream\n"; |
| 20 stream->write(streamBegin, strlen(streamBegin)); | 19 stream->write(streamBegin, strlen(streamBegin)); |
| 21 } | 20 } |
| 22 | 21 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 236 } |
| 238 | 237 |
| 239 //////////////////////////////////////////////////////////////////////////////// | 238 //////////////////////////////////////////////////////////////////////////////// |
| 240 | 239 |
| 241 namespace { | 240 namespace { |
| 242 // This SkPDFObject only outputs the alpha layer of the given bitmap. | 241 // This SkPDFObject only outputs the alpha layer of the given bitmap. |
| 243 class PDFAlphaBitmap : public SkPDFObject { | 242 class PDFAlphaBitmap : public SkPDFObject { |
| 244 public: | 243 public: |
| 245 PDFAlphaBitmap(const SkBitmap& bm) : fBitmap(bm) {} | 244 PDFAlphaBitmap(const SkBitmap& bm) : fBitmap(bm) {} |
| 246 ~PDFAlphaBitmap() {} | 245 ~PDFAlphaBitmap() {} |
| 247 void emitObject(SkWStream*, SkPDFCatalog*) override; | 246 void emitObject(SkWStream*, |
| 247 const SkPDFObjNumMap&, |
| 248 const SkPDFSubstituteMap&) override; |
| 248 | 249 |
| 249 private: | 250 private: |
| 250 const SkBitmap fBitmap; | 251 const SkBitmap fBitmap; |
| 251 void emitDict(SkWStream*, SkPDFCatalog*, size_t) const; | |
| 252 }; | 252 }; |
| 253 | 253 |
| 254 void PDFAlphaBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 254 void PDFAlphaBitmap::emitObject(SkWStream* stream, |
| 255 const SkPDFObjNumMap& objNumMap, |
| 256 const SkPDFSubstituteMap& substitutes) { |
| 255 SkAutoLockPixels autoLockPixels(fBitmap); | 257 SkAutoLockPixels autoLockPixels(fBitmap); |
| 256 SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType || | 258 SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType || |
| 257 fBitmap.getColorTable()); | 259 fBitmap.getColorTable()); |
| 258 | 260 |
| 259 // Write to a temporary buffer to get the compressed length. | 261 // Write to a temporary buffer to get the compressed length. |
| 260 SkDynamicMemoryWStream buffer; | 262 SkDynamicMemoryWStream buffer; |
| 261 SkDeflateWStream deflateWStream(&buffer); | 263 SkDeflateWStream deflateWStream(&buffer); |
| 262 bitmap_alpha_to_a8(fBitmap, &deflateWStream); | 264 bitmap_alpha_to_a8(fBitmap, &deflateWStream); |
| 263 deflateWStream.finalize(); // call before detachAsStream(). | 265 deflateWStream.finalize(); // call before detachAsStream(). |
| 264 SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream()); | 266 SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream()); |
| 265 | 267 |
| 266 this->emitDict(stream, catalog, asset->getLength()); | |
| 267 pdf_stream_begin(stream); | |
| 268 stream->writeStream(asset.get(), asset->getLength()); | |
| 269 pdf_stream_end(stream); | |
| 270 } | |
| 271 | |
| 272 void PDFAlphaBitmap::emitDict(SkWStream* stream, | |
| 273 SkPDFCatalog* catalog, | |
| 274 size_t length) const { | |
| 275 SkPDFDict pdfDict("XObject"); | 268 SkPDFDict pdfDict("XObject"); |
| 276 pdfDict.insertName("Subtype", "Image"); | 269 pdfDict.insertName("Subtype", "Image"); |
| 277 pdfDict.insertInt("Width", fBitmap.width()); | 270 pdfDict.insertInt("Width", fBitmap.width()); |
| 278 pdfDict.insertInt("Height", fBitmap.height()); | 271 pdfDict.insertInt("Height", fBitmap.height()); |
| 279 pdfDict.insertName("ColorSpace", "DeviceGray"); | 272 pdfDict.insertName("ColorSpace", "DeviceGray"); |
| 280 pdfDict.insertInt("BitsPerComponent", 8); | 273 pdfDict.insertInt("BitsPerComponent", 8); |
| 281 pdfDict.insertName("Filter", "FlateDecode"); | 274 pdfDict.insertName("Filter", "FlateDecode"); |
| 282 pdfDict.insertInt("Length", length); | 275 pdfDict.insertInt("Length", asset->getLength()); |
| 283 pdfDict.emitObject(stream, catalog); | 276 pdfDict.emitObject(stream, objNumMap, substitutes); |
| 277 |
| 278 pdf_stream_begin(stream); |
| 279 stream->writeStream(asset.get(), asset->getLength()); |
| 280 pdf_stream_end(stream); |
| 284 } | 281 } |
| 285 } // namespace | 282 } // namespace |
| 286 | 283 |
| 287 //////////////////////////////////////////////////////////////////////////////// | 284 //////////////////////////////////////////////////////////////////////////////// |
| 288 | 285 |
| 289 void SkPDFBitmap::addResources(SkPDFCatalog* catalog) const { | 286 void SkPDFBitmap::addResources(SkPDFObjNumMap* catalog, |
| 287 const SkPDFSubstituteMap& substitutes) const { |
| 290 if (fSMask.get()) { | 288 if (fSMask.get()) { |
| 291 if (catalog->addObject(fSMask.get())) { | 289 SkPDFObject* obj = substitutes.getSubstitute(fSMask.get()); |
| 292 fSMask->addResources(catalog); | 290 SkASSERT(obj); |
| 291 if (catalog->addObject(obj)) { |
| 292 obj->addResources(catalog, substitutes); |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 } | 295 } |
| 296 | 296 |
| 297 void SkPDFBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | |
| 298 SkAutoLockPixels autoLockPixels(fBitmap); | |
| 299 SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType || | |
| 300 fBitmap.getColorTable()); | |
| 301 | |
| 302 // Write to a temporary buffer to get the compressed length. | |
| 303 SkDynamicMemoryWStream buffer; | |
| 304 SkDeflateWStream deflateWStream(&buffer); | |
| 305 bitmap_to_pdf_pixels(fBitmap, &deflateWStream); | |
| 306 deflateWStream.finalize(); // call before detachAsStream(). | |
| 307 SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream()); | |
| 308 | |
| 309 this->emitDict(stream, catalog, asset->getLength()); | |
| 310 pdf_stream_begin(stream); | |
| 311 stream->writeStream(asset.get(), asset->getLength()); | |
| 312 pdf_stream_end(stream); | |
| 313 } | |
| 314 | |
| 315 static SkPDFArray* make_indexed_color_space(const SkColorTable* table) { | 297 static SkPDFArray* make_indexed_color_space(const SkColorTable* table) { |
| 316 SkPDFArray* result = SkNEW(SkPDFArray); | 298 SkPDFArray* result = SkNEW(SkPDFArray); |
| 317 result->reserve(4); | 299 result->reserve(4); |
| 318 result->appendName("Indexed"); | 300 result->appendName("Indexed"); |
| 319 result->appendName("DeviceRGB"); | 301 result->appendName("DeviceRGB"); |
| 320 SkASSERT(table); | 302 SkASSERT(table); |
| 321 if (table->count() < 1) { | 303 if (table->count() < 1) { |
| 322 result->appendInt(0); | 304 result->appendInt(0); |
| 323 char shortTableArray[3] = {0, 0, 0}; | 305 char shortTableArray[3] = {0, 0, 0}; |
| 324 SkString tableString(shortTableArray, SK_ARRAY_COUNT(shortTableArray)); | 306 SkString tableString(shortTableArray, SK_ARRAY_COUNT(shortTableArray)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 335 const SkPMColor* colors = table->readColors(); | 317 const SkPMColor* colors = table->readColors(); |
| 336 for (int i = 0; i < table->count(); i++) { | 318 for (int i = 0; i < table->count(); i++) { |
| 337 pmcolor_to_rgb24(colors[i], tablePtr); | 319 pmcolor_to_rgb24(colors[i], tablePtr); |
| 338 tablePtr += 3; | 320 tablePtr += 3; |
| 339 } | 321 } |
| 340 SkString tableString(tableArray, 3 * table->count()); | 322 SkString tableString(tableArray, 3 * table->count()); |
| 341 result->append(new SkPDFString(tableString))->unref(); | 323 result->append(new SkPDFString(tableString))->unref(); |
| 342 return result; | 324 return result; |
| 343 } | 325 } |
| 344 | 326 |
| 345 void SkPDFBitmap::emitDict(SkWStream* stream, | 327 void SkPDFBitmap::emitObject(SkWStream* stream, |
| 346 SkPDFCatalog* catalog, | 328 const SkPDFObjNumMap& objNumMap, |
| 347 size_t length) const { | 329 const SkPDFSubstituteMap& substitutes) { |
| 330 SkAutoLockPixels autoLockPixels(fBitmap); |
| 331 SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType || |
| 332 fBitmap.getColorTable()); |
| 333 |
| 334 // Write to a temporary buffer to get the compressed length. |
| 335 SkDynamicMemoryWStream buffer; |
| 336 SkDeflateWStream deflateWStream(&buffer); |
| 337 bitmap_to_pdf_pixels(fBitmap, &deflateWStream); |
| 338 deflateWStream.finalize(); // call before detachAsStream(). |
| 339 SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream()); |
| 340 |
| 348 SkPDFDict pdfDict("XObject"); | 341 SkPDFDict pdfDict("XObject"); |
| 349 pdfDict.insertName("Subtype", "Image"); | 342 pdfDict.insertName("Subtype", "Image"); |
| 350 pdfDict.insertInt("Width", fBitmap.width()); | 343 pdfDict.insertInt("Width", fBitmap.width()); |
| 351 pdfDict.insertInt("Height", fBitmap.height()); | 344 pdfDict.insertInt("Height", fBitmap.height()); |
| 352 if (fBitmap.colorType() == kIndex_8_SkColorType) { | 345 if (fBitmap.colorType() == kIndex_8_SkColorType) { |
| 353 SkASSERT(1 == pdf_color_component_count(fBitmap.colorType())); | 346 SkASSERT(1 == pdf_color_component_count(fBitmap.colorType())); |
| 354 pdfDict.insert("ColorSpace", make_indexed_color_space( | 347 pdfDict.insert("ColorSpace", make_indexed_color_space( |
| 355 fBitmap.getColorTable()))->unref(); | 348 fBitmap.getColorTable()))->unref(); |
| 356 } else if (1 == pdf_color_component_count(fBitmap.colorType())) { | 349 } else if (1 == pdf_color_component_count(fBitmap.colorType())) { |
| 357 pdfDict.insertName("ColorSpace", "DeviceGray"); | 350 pdfDict.insertName("ColorSpace", "DeviceGray"); |
| 358 } else { | 351 } else { |
| 359 pdfDict.insertName("ColorSpace", "DeviceRGB"); | 352 pdfDict.insertName("ColorSpace", "DeviceRGB"); |
| 360 } | 353 } |
| 361 pdfDict.insertInt("BitsPerComponent", 8); | 354 pdfDict.insertInt("BitsPerComponent", 8); |
| 362 if (fSMask) { | 355 if (fSMask) { |
| 363 pdfDict.insert("SMask", new SkPDFObjRef(fSMask))->unref(); | 356 pdfDict.insert("SMask", new SkPDFObjRef(fSMask))->unref(); |
| 364 } | 357 } |
| 365 pdfDict.insertName("Filter", "FlateDecode"); | 358 pdfDict.insertName("Filter", "FlateDecode"); |
| 366 pdfDict.insertInt("Length", length); | 359 pdfDict.insertInt("Length", asset->getLength()); |
| 367 pdfDict.emitObject(stream, catalog); | 360 pdfDict.emitObject(stream, objNumMap,substitutes); |
| 361 |
| 362 pdf_stream_begin(stream); |
| 363 stream->writeStream(asset.get(), asset->getLength()); |
| 364 pdf_stream_end(stream); |
| 368 } | 365 } |
| 369 | 366 |
| 370 SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm, | 367 SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm, |
| 371 SkPDFObject* smask) | 368 SkPDFObject* smask) |
| 372 : fBitmap(bm), fSMask(smask) {} | 369 : fBitmap(bm), fSMask(smask) {} |
| 373 | 370 |
| 374 SkPDFBitmap::~SkPDFBitmap() {} | 371 SkPDFBitmap::~SkPDFBitmap() {} |
| 375 | 372 |
| 376 //////////////////////////////////////////////////////////////////////////////// | 373 //////////////////////////////////////////////////////////////////////////////// |
| 377 | 374 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 399 return SkRef(canonBitmap); | 396 return SkRef(canonBitmap); |
| 400 } | 397 } |
| 401 SkPDFObject* smask = NULL; | 398 SkPDFObject* smask = NULL; |
| 402 if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) { | 399 if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) { |
| 403 smask = SkNEW_ARGS(PDFAlphaBitmap, (bm)); | 400 smask = SkNEW_ARGS(PDFAlphaBitmap, (bm)); |
| 404 } | 401 } |
| 405 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, smask)); | 402 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, smask)); |
| 406 canon->addBitmap(pdfBitmap); | 403 canon->addBitmap(pdfBitmap); |
| 407 return pdfBitmap; | 404 return pdfBitmap; |
| 408 } | 405 } |
| OLD | NEW |