| 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 |