OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 The Android Open Source Project | 2 * Copyright 2010 The Android Open Source Project |
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 "SkPDFImage.h" | 8 #include "SkPDFImage.h" |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 const SkIRect& srcRect) { | 29 const SkIRect& srcRect) { |
30 switch (bitmap.config()) { | 30 switch (bitmap.config()) { |
31 case SkBitmap::kIndex8_Config: | 31 case SkBitmap::kIndex8_Config: |
32 return srcRect.width() * srcRect.height(); | 32 return srcRect.width() * srcRect.height(); |
33 case SkBitmap::kARGB_4444_Config: | 33 case SkBitmap::kARGB_4444_Config: |
34 return ((srcRect.width() * 3 + 1) / 2) * srcRect.height(); | 34 return ((srcRect.width() * 3 + 1) / 2) * srcRect.height(); |
35 case SkBitmap::kRGB_565_Config: | 35 case SkBitmap::kRGB_565_Config: |
36 return srcRect.width() * 3 * srcRect.height(); | 36 return srcRect.width() * 3 * srcRect.height(); |
37 case SkBitmap::kARGB_8888_Config: | 37 case SkBitmap::kARGB_8888_Config: |
38 return srcRect.width() * 3 * srcRect.height(); | 38 return srcRect.width() * 3 * srcRect.height(); |
39 case SkBitmap::kA1_Config: | |
40 case SkBitmap::kA8_Config: | 39 case SkBitmap::kA8_Config: |
41 return 1; | 40 return 1; |
42 default: | 41 default: |
43 SkASSERT(false); | 42 SkASSERT(false); |
44 return 0; | 43 return 0; |
45 } | 44 } |
46 } | 45 } |
47 | 46 |
48 static SkStream* extract_index8_image(const SkBitmap& bitmap, | 47 static SkStream* extract_index8_image(const SkBitmap& bitmap, |
49 const SkIRect& srcRect) { | 48 const SkIRect& srcRect) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 dst[0] = SkGetPackedR32(src[x]); | 158 dst[0] = SkGetPackedR32(src[x]); |
160 dst[1] = SkGetPackedG32(src[x]); | 159 dst[1] = SkGetPackedG32(src[x]); |
161 dst[2] = SkGetPackedB32(src[x]); | 160 dst[2] = SkGetPackedB32(src[x]); |
162 dst += 3; | 161 dst += 3; |
163 } | 162 } |
164 } | 163 } |
165 } | 164 } |
166 return stream; | 165 return stream; |
167 } | 166 } |
168 | 167 |
169 static SkStream* extract_a1_alpha(const SkBitmap& bitmap, | |
170 const SkIRect& srcRect, | |
171 bool* isOpaque, | |
172 bool* isTransparent) { | |
173 const int alphaRowBytes = (srcRect.width() + 7) / 8; | |
174 SkStream* stream = SkNEW_ARGS(SkMemoryStream, | |
175 (alphaRowBytes * srcRect.height())); | |
176 uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase(); | |
177 | |
178 int offset1 = srcRect.fLeft % 8; | |
179 int offset2 = 8 - offset1; | |
180 | |
181 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { | |
182 uint8_t* src = bitmap.getAddr1(0, y); | |
183 // This may read up to one byte after src, but the | |
184 // potentially invalid bits are never used for computation. | |
185 for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) { | |
186 if (offset1) { | |
187 alphaDst[0] = src[x / 8] << offset1 | | |
188 src[x / 8 + 1] >> offset2; | |
189 } else { | |
190 alphaDst[0] = src[x / 8]; | |
191 } | |
192 if (x + 7 < srcRect.fRight) { | |
193 *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE; | |
194 *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT; | |
195 } | |
196 alphaDst++; | |
197 } | |
198 // Calculate the mask of bits we're interested in within the | |
199 // last byte of alphaDst. | |
200 // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE | |
201 uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1); | |
202 if (srcRect.width() % 8) { | |
203 *isOpaque &= (alphaDst[-1] & mask) == (SK_AlphaOPAQUE & mask); | |
204 *isTransparent &= | |
205 (alphaDst[-1] & mask) == (SK_AlphaTRANSPARENT & mask); | |
206 } | |
207 } | |
208 return stream; | |
209 } | |
210 | |
211 static SkStream* extract_a8_alpha(const SkBitmap& bitmap, | 168 static SkStream* extract_a8_alpha(const SkBitmap& bitmap, |
212 const SkIRect& srcRect, | 169 const SkIRect& srcRect, |
213 bool* isOpaque, | 170 bool* isOpaque, |
214 bool* isTransparent) { | 171 bool* isTransparent) { |
215 const int alphaRowBytes = srcRect.width(); | 172 const int alphaRowBytes = srcRect.width(); |
216 SkStream* stream = SkNEW_ARGS(SkMemoryStream, | 173 SkStream* stream = SkNEW_ARGS(SkMemoryStream, |
217 (alphaRowBytes * srcRect.height())); | 174 (alphaRowBytes * srcRect.height())); |
218 uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase(); | 175 uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase(); |
219 | 176 |
220 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { | 177 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 break; | 233 break; |
277 case SkBitmap::kRGB_565_Config: | 234 case SkBitmap::kRGB_565_Config: |
278 if (!extractAlpha) { | 235 if (!extractAlpha) { |
279 stream = extract_rgb565_image(bitmap, srcRect); | 236 stream = extract_rgb565_image(bitmap, srcRect); |
280 } | 237 } |
281 break; | 238 break; |
282 case SkBitmap::kARGB_8888_Config: | 239 case SkBitmap::kARGB_8888_Config: |
283 stream = extract_argb8888_data(bitmap, srcRect, extractAlpha, | 240 stream = extract_argb8888_data(bitmap, srcRect, extractAlpha, |
284 &isOpaque, &transparent); | 241 &isOpaque, &transparent); |
285 break; | 242 break; |
286 case SkBitmap::kA1_Config: | |
287 if (!extractAlpha) { | |
288 stream = create_black_image(); | |
289 } else { | |
290 stream = extract_a1_alpha(bitmap, srcRect, | |
291 &isOpaque, &transparent); | |
292 } | |
293 break; | |
294 case SkBitmap::kA8_Config: | 243 case SkBitmap::kA8_Config: |
295 if (!extractAlpha) { | 244 if (!extractAlpha) { |
296 stream = create_black_image(); | 245 stream = create_black_image(); |
297 } else { | 246 } else { |
298 stream = extract_a8_alpha(bitmap, srcRect, | 247 stream = extract_a8_alpha(bitmap, srcRect, |
299 &isOpaque, &transparent); | 248 &isOpaque, &transparent); |
300 } | 249 } |
301 break; | 250 break; |
302 default: | 251 default: |
303 SkASSERT(false); | 252 SkASSERT(false); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 fStreamValid = true; | 516 fStreamValid = true; |
568 } else { | 517 } else { |
569 fStreamValid = false; | 518 fStreamValid = false; |
570 } | 519 } |
571 | 520 |
572 SkBitmap::Config config = fBitmap.config(); | 521 SkBitmap::Config config = fBitmap.config(); |
573 | 522 |
574 insertName("Type", "XObject"); | 523 insertName("Type", "XObject"); |
575 insertName("Subtype", "Image"); | 524 insertName("Subtype", "Image"); |
576 | 525 |
577 bool alphaOnly = (config == SkBitmap::kA1_Config || | 526 bool alphaOnly = (config == SkBitmap::kA8_Config); |
578 config == SkBitmap::kA8_Config); | |
579 | 527 |
580 if (!isAlpha && alphaOnly) { | 528 if (!isAlpha && alphaOnly) { |
581 // For alpha only images, we stretch a single pixel of black for | 529 // For alpha only images, we stretch a single pixel of black for |
582 // the color/shape part. | 530 // the color/shape part. |
583 SkAutoTUnref<SkPDFInt> one(new SkPDFInt(1)); | 531 SkAutoTUnref<SkPDFInt> one(new SkPDFInt(1)); |
584 insert("Width", one.get()); | 532 insert("Width", one.get()); |
585 insert("Height", one.get()); | 533 insert("Height", one.get()); |
586 } else { | 534 } else { |
587 insertInt("Width", fSrcRect.width()); | 535 insertInt("Width", fSrcRect.width()); |
588 insertInt("Height", fSrcRect.height()); | 536 insertInt("Height", fSrcRect.height()); |
589 } | 537 } |
590 | 538 |
591 if (isAlpha || alphaOnly) { | 539 if (isAlpha || alphaOnly) { |
592 insertName("ColorSpace", "DeviceGray"); | 540 insertName("ColorSpace", "DeviceGray"); |
593 } else if (config == SkBitmap::kIndex8_Config) { | 541 } else if (config == SkBitmap::kIndex8_Config) { |
594 SkAutoLockPixels alp(fBitmap); | 542 SkAutoLockPixels alp(fBitmap); |
595 insert("ColorSpace", | 543 insert("ColorSpace", |
596 make_indexed_color_space(fBitmap.getColorTable()))->unref(); | 544 make_indexed_color_space(fBitmap.getColorTable()))->unref(); |
597 } else { | 545 } else { |
598 insertName("ColorSpace", "DeviceRGB"); | 546 insertName("ColorSpace", "DeviceRGB"); |
599 } | 547 } |
600 | 548 |
601 int bitsPerComp = 8; | 549 int bitsPerComp = 8; |
602 if (config == SkBitmap::kARGB_4444_Config) { | 550 if (config == SkBitmap::kARGB_4444_Config) { |
603 bitsPerComp = 4; | 551 bitsPerComp = 4; |
604 } else if (isAlpha && config == SkBitmap::kA1_Config) { | |
605 bitsPerComp = 1; | |
606 } | 552 } |
607 insertInt("BitsPerComponent", bitsPerComp); | 553 insertInt("BitsPerComponent", bitsPerComp); |
608 | 554 |
609 if (config == SkBitmap::kRGB_565_Config) { | 555 if (config == SkBitmap::kRGB_565_Config) { |
610 SkASSERT(!isAlpha); | 556 SkASSERT(!isAlpha); |
611 SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0)); | 557 SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0)); |
612 SkAutoTUnref<SkPDFScalar> scale5Val( | 558 SkAutoTUnref<SkPDFScalar> scale5Val( |
613 new SkPDFScalar(SkFloatToScalar(8.2258f))); // 255/2^5-1 | 559 new SkPDFScalar(SkFloatToScalar(8.2258f))); // 255/2^5-1 |
614 SkAutoTUnref<SkPDFScalar> scale6Val( | 560 SkAutoTUnref<SkPDFScalar> scale6Val( |
615 new SkPDFScalar(SkFloatToScalar(4.0476f))); // 255/2^6-1 | 561 new SkPDFScalar(SkFloatToScalar(4.0476f))); // 255/2^6-1 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 // but the new catalog wants it compressed. | 626 // but the new catalog wants it compressed. |
681 if (!getSubstitute()) { | 627 if (!getSubstitute()) { |
682 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); | 628 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); |
683 setSubstitute(substitute); | 629 setSubstitute(substitute); |
684 catalog->setSubstitute(this, substitute); | 630 catalog->setSubstitute(this, substitute); |
685 } | 631 } |
686 return false; | 632 return false; |
687 } | 633 } |
688 return true; | 634 return true; |
689 } | 635 } |
OLD | NEW |