Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/pdf/SkPDFBitmap.cpp

Issue 918813002: PDF: Add (low-memory) SkPDFBitmap class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-02-11 (Wednesday) 18:49:13 EST Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 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 "SkPDFBitmap.h"
9 #include "SkPDFCanon.h"
10 #include "SkUnPreMultiply.h"
11 #include "SkColorPriv.h"
12 #include "SkStream.h"
13 #include "SkDeflateWStream.h"
14 #include "SkFlate.h"
15
16 static void emit_pdf_bitmap_dict(SkWStream* stream,
17 SkPDFCatalog* catalog,
18 SkISize dimensions,
19 int32_t length,
20 SkPDFObject* smask,
21 bool deflate,
22 const char colorSpace[]) {
23 SkPDFDict pdfDict("Xobject");
24 pdfDict.insertName("Subtype", "Image");
25 pdfDict.insertInt("Width", dimensions.width());
26 pdfDict.insertInt("Height", dimensions.height());
27 pdfDict.insertName("ColorSpace", colorSpace);
28 pdfDict.insertInt("BitsPerComponent", 8);
29 if (smask) {
30 pdfDict.insert("SMask", new SkPDFObjRef(smask))->unref();
31 }
32 pdfDict.insertInt("Length", length);
33 if (deflate) {
34 pdfDict.insertName("Filter", "FlateDecode");
35 }
36 pdfDict.emitObject(stream, catalog);
37 }
38
39 static void pmcolor_scanline_to_rgb24(const SkPMColor* src,
mtklein 2015/02/12 00:21:46 This is just a suggestion. I've grown to like (ds
hal.canary 2015/02/12 21:28:03 Refactored out.
40 uint8_t* dst, int width) {
41 for (int x = 0; x < width; ++x) {
42 const SkPMColor pmColor = *src++;
43 const uint32_t s = SkUnPreMultiply::GetScale(SkGetPackedA32(pmColor));
44 *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(pmColor));
45 *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedG32(pmColor));
46 *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(pmColor));
47 }
48 }
49
50 static void pmcolor_alpha_scanline_to_a8(const SkPMColor* src,
51 uint8_t* dst, int width) {
52 for (int x = 0; x < width; ++x) {
53 *dst++ = SkGetPackedA32(*src++);
54 }
55 }
56
57 SkPDFBitmap::~SkPDFBitmap() {
58 if (!fIsAlpha) {
mtklein 2015/02/12 00:21:46 It'd be nice to explain fIsAlpha and why we track
hal.canary 2015/02/12 21:28:03 Done.
59 SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
60 SkPDFCanon::GetCanon().removeBitmap(this);
61 }
62 }
63
64 void SkPDFBitmap::addResources(SkTSet<SkPDFObject*>* resourceSet,
65 SkPDFCatalog* catalog) const {
66 if (fSMask.get()) {
67 resourceSet->add(fSMask.get());
68 }
69 }
70
71 void SkPDFBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
72 SkASSERT(kN32_SkColorType == fBitmap.colorType());
73 SkAutoLockPixels autoLockPixels(fBitmap);
74 SkASSERT(fBitmap.getPixels());
75
76 if (SkFlate::HaveFlate()) {
77 SkDynamicMemoryWStream buffer;
78 size_t scanlineLength = fIsAlpha ? fBitmap.width()
79 : 3 * fBitmap.width();
80 SkAutoTMalloc<uint8_t> scanline(scanlineLength);
81 if (fIsAlpha) {
82 SkDeflateWStream deflateWStream(&buffer);
83 for (int y = 0; y < fBitmap.height(); ++y) {
84 pmcolor_alpha_scanline_to_a8(fBitmap.getAddr32(0, y),
85 scanline.get(),
86 fBitmap.width());
87 deflateWStream.write(scanline.get(), scanlineLength);
88 }
89 // deflateWStream is deleted.
mtklein 2015/02/12 00:21:46 Is this salient here but not in the rgb case?
hal.canary 2015/02/12 21:28:03 refactored out
90 } else {
91 SkDeflateWStream deflateWStream(&buffer);
92 for (int y = 0; y < fBitmap.height(); ++y) {
93 pmcolor_scanline_to_rgb24(fBitmap.getAddr32(0, y),
94 scanline.get(),
95 fBitmap.width());
96 deflateWStream.write(scanline.get(), scanlineLength);
97 }
98 }
99 SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
100 emit_pdf_bitmap_dict(stream,
101 catalog,
102 fBitmap.dimensions(),
103 asset->getLength(),
104 fSMask,
105 true,
mtklein 2015/02/12 00:21:46 Is this /* using DEFLATE */ and false /* not compr
106 fIsAlpha ? "DeviceGray" : "DeviceRGB");
107 stream->writeText(" stream\n");
108 stream->writeStream(asset.get(), asset->getLength());
109 stream->writeText("\nendstream");
110 return;
111 } else { // !SkFlate::HaveFlate()
112 size_t scanlineLength = fIsAlpha ? fBitmap.width()
mtklein 2015/02/12 00:21:46 Seems like an awful lot of code duplicated between
113 : 3 * fBitmap.width();
114 emit_pdf_bitmap_dict(stream,
115 catalog,
116 fBitmap.dimensions(),
117 fBitmap.height() * scanlineLength,
118 fSMask,
119 false,
120 fIsAlpha ? "DeviceGray" : "DeviceRGB");
121 stream->writeText(" stream\n");
122
123 SkAutoTMalloc<uint8_t> scanline(scanlineLength);
124
125 if (fIsAlpha) {
126 for (int y = 0; y < fBitmap.height(); ++y) {
127 pmcolor_alpha_scanline_to_a8(fBitmap.getAddr32(0, y),
128 scanline.get(),
129 fBitmap.width());
130 stream->write(scanline.get(), scanlineLength);
131 }
132 } else {
133 for (int y = 0; y < fBitmap.height(); ++y) {
134 pmcolor_scanline_to_rgb24(fBitmap.getAddr32(0, y),
135 scanline.get(),
136 fBitmap.width());
137 stream->write(scanline.get(), scanlineLength);
138 }
139 }
140 stream->writeText("\nendstream");
141 return;
142 }
143 }
144
145 SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm, bool isAlpha, SkPDFBitmap* smask)
146 : fBitmap(bm), fSMask(smask), fIsAlpha(isAlpha) {}
147
148 SkPDFBitmap* SkPDFBitmap::Create(const SkBitmap& bitmap,
149 const SkIRect& subset) {
150 if (kN32_SkColorType != bitmap.colorType()) {
151 return NULL;
152 }
153 SkBitmap bm;
154 if (!bitmap.extractSubset(&bm, subset)) {
155 return NULL;
156 }
157 if (bm.drawsNothing()) {
158 return NULL;
mtklein 2015/02/12 00:21:46 Is this really an error?
hal.canary 2015/02/12 21:28:03 Just a shortcut.
159 }
160 SkAutoMutexAcquire autoMutexAcquire(SkPDFCanon::GetBitmapMutex());
161 SkPDFCanon& canon = SkPDFCanon::GetCanon();
162 SkPDFBitmap* pdfBitmap = canon.findBitmap(bm);
163 if (pdfBitmap) {
164 return SkRef(pdfBitmap);
165 } // src/pdf/SkPDFBitmap.cpp
166 SkPDFBitmap* smask = NULL;
167 if (!bitmap.isOpaque() && !SkBitmap::ComputeIsOpaque(bitmap)) {
168 smask = SkNEW_ARGS(SkPDFBitmap, (bm, true, NULL));
mtklein 2015/02/12 00:21:46 Are the smasks always alpha-only and the main SkPD
hal.canary 2015/02/12 21:28:03 Okay, done. Seems like more code this way.
169 }
170 pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, false, smask));
171 canon.addBitmap(pdfBitmap);
172 return pdfBitmap;
173 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698