From befebb8a8437ce69e3a416b417cb27b66273128d Mon Sep 17 00:00:00 2001 From: "vandebo@chromium.org" Date: Sat, 29 Jan 2011 01:38:50 +0000 Subject: [PATCH] [PDF] Honor srcRect in drawBitmap. Review URL: http://codereview.appspot.com/4083045 git-svn-id: http://skia.googlecode.com/svn/trunk@745 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/pdf/SkPDFDevice.h | 2 +- include/pdf/SkPDFImage.h | 4 +- src/pdf/SkPDFDevice.cpp | 17 ++++---- src/pdf/SkPDFImage.cpp | 101 ++++++++++++++++++++++++---------------------- 4 files changed, 67 insertions(+), 57 deletions(-) diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 7395373..b6bc7be 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -178,7 +178,7 @@ private: void popGS(); void setTextTransform(SkScalar x, SkScalar y, SkScalar textSkewX); void internalDrawBitmap(const SkMatrix& matrix, const SkBitmap& bitmap, - const SkPaint& paint); + const SkIRect* srcRect, const SkPaint& paint); SkMatrix setTransform(const SkMatrix& matrix); }; diff --git a/include/pdf/SkPDFImage.h b/include/pdf/SkPDFImage.h index 6e5ee37..48d6398 100644 --- a/include/pdf/SkPDFImage.h +++ b/include/pdf/SkPDFImage.h @@ -22,6 +22,7 @@ #include "SkRefCnt.h" class SkBitmap; +class SkIRect; class SkPaint; class SkPDFCatalog; @@ -40,7 +41,8 @@ public: * @param bitmap The image to use. * @param paint Used to calculate alpha, masks, etc. */ - SkPDFImage(const SkBitmap& bitmap, const SkPaint& paint); + SkPDFImage(const SkBitmap& bitmap, const SkIRect& srcRect, + const SkPaint& paint); virtual ~SkPDFImage(); // The SkPDFObject interface. diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 4cbdf9c..b98e4af 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -266,7 +266,7 @@ void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r, void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { - NOT_IMPLEMENTED("drawPath with prePathMatrix", (prePathMatrix != NULL)); + NOT_IMPLEMENTED(prePathMatrix != NULL, true); if (paint.getPathEffect()) { // Apply the path effect to path and draw it that way. @@ -287,18 +287,16 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path, void SkPDFDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { - // TODO: respect srcRect if present - SkMatrix transform = matrix; transform.postConcat(fGraphicStack[fGraphicStackIndex].fTransform); - internalDrawBitmap(transform, bitmap, paint); + internalDrawBitmap(transform, bitmap, srcRect, paint); } void SkPDFDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { SkMatrix matrix; matrix.setTranslate(x, y); - internalDrawBitmap(matrix, bitmap, paint); + internalDrawBitmap(matrix, bitmap, NULL, paint); } void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, @@ -813,17 +811,22 @@ void SkPDFDevice::setTextTransform(SkScalar x, SkScalar y, SkScalar textSkewX) { void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix, const SkBitmap& bitmap, + const SkIRect* srcRect, const SkPaint& paint) { + SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height()); + if (srcRect && !subset.intersect(*srcRect)) + return; + SkMatrix scaled; // Adjust for origin flip. scaled.setScale(1, -1); scaled.postTranslate(0, 1); // Scale the image up from 1x1 to WxH. - scaled.postScale(bitmap.width(), bitmap.height()); + scaled.postScale(subset.width(), subset.height()); scaled.postConcat(matrix); SkMatrix curTransform = setTransform(scaled); - SkPDFImage* image = new SkPDFImage(bitmap, paint); + SkPDFImage* image = new SkPDFImage(bitmap, subset, paint); fXObjectResources.push(image); // Transfer reference. fContent.append("/X"); fContent.appendS32(fXObjectResources.count() - 1); diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp index 2162eae..51bf8ae 100644 --- a/src/pdf/SkPDFImage.cpp +++ b/src/pdf/SkPDFImage.cpp @@ -22,87 +22,91 @@ #include "SkPaint.h" #include "SkPackBits.h" #include "SkPDFCatalog.h" +#include "SkRect.h" #include "SkStream.h" #include "SkString.h" #include "SkUnPreMultiply.h" namespace { -SkMemoryStream* extractImageData(const SkBitmap& bitmap) { +SkMemoryStream* extractImageData(const SkBitmap& bitmap, + const SkIRect& srcRect) { SkMemoryStream* result = NULL; bitmap.lockPixels(); switch (bitmap.getConfig()) { - case SkBitmap::kIndex8_Config: - result = new SkMemoryStream(bitmap.getPixels(), bitmap.getSize(), - true); + case SkBitmap::kIndex8_Config: { + const int rowBytes = srcRect.width(); + result = new SkMemoryStream(rowBytes * srcRect.height()); + uint8_t* dst = (uint8_t*)result->getMemoryBase(); + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { + memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes); + dst += rowBytes; + } break; + } case SkBitmap::kRLE_Index8_Config: { - result = new SkMemoryStream(bitmap.getSize()); + const int rowBytes = srcRect.width(); + result = new SkMemoryStream(rowBytes * srcRect.height()); + uint8_t* dst = (uint8_t*)result->getMemoryBase(); const SkBitmap::RLEPixels* rle = (const SkBitmap::RLEPixels*)bitmap.getPixels(); - uint8_t* dst = (uint8_t*)result->getMemoryBase(); - const int width = bitmap.width(); - for (int y = 0; y < bitmap.height(); y++) { - SkPackBits::Unpack8(rle->packedAtY(y), width, dst); - dst += width; + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { + SkPackBits::Unpack8(dst, srcRect.fLeft, rowBytes, + rle->packedAtY(y)); + dst += rowBytes; } break; } case SkBitmap::kARGB_4444_Config: { - const int width = bitmap.width(); - const int rowBytes = (width * 3 + 1) / 2; - result = new SkMemoryStream(rowBytes * bitmap.height()); + const int rowBytes = (srcRect.width() * 3 + 1) / 2; + result = new SkMemoryStream(rowBytes * srcRect.height()); uint8_t* dst = (uint8_t*)result->getMemoryBase(); - for (int y = 0; y < bitmap.height(); y++) { + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint16_t* src = bitmap.getAddr16(0, y); - for (int x = 0; x < width; x += 2) { - dst[0] = (SkGetPackedR4444(src[0]) << 4) | - SkGetPackedG4444(src[0]); - dst[1] = (SkGetPackedB4444(src[0]) << 4) | - SkGetPackedR4444(src[1]); - dst[2] = (SkGetPackedG4444(src[1]) << 4) | - SkGetPackedB4444(src[1]); - src += 2; + int x; + for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) { + dst[0] = (SkGetPackedR4444(src[x]) << 4) | + SkGetPackedG4444(src[x]); + dst[1] = (SkGetPackedB4444(src[x]) << 4) | + SkGetPackedR4444(src[x + 1]); + dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) | + SkGetPackedB4444(src[x + 1]); dst += 3; } - if (width & 1) { - dst[0] = (SkGetPackedR4444(src[0]) << 4) | - SkGetPackedG4444(src[0]); - dst[1] = (SkGetPackedB4444(src[0]) << 4); + if (srcRect.width() & 1) { + dst[0] = (SkGetPackedR4444(src[x]) << 4) | + SkGetPackedG4444(src[x]); + dst[1] = (SkGetPackedB4444(src[x]) << 4); } } break; } case SkBitmap::kRGB_565_Config: { - const int width = bitmap.width(); - const int rowBytes = width * 3; - result = new SkMemoryStream(rowBytes * bitmap.height()); + const int rowBytes = srcRect.width() * 3; + result = new SkMemoryStream(rowBytes * srcRect.height()); uint8_t* dst = (uint8_t*)result->getMemoryBase(); - for (int y = 0; y < bitmap.height(); y++) { + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint16_t* src = bitmap.getAddr16(0, y); - for (int x = 0; x < width; x++) { - dst[0] = SkGetPackedR16(src[0]); - dst[1] = SkGetPackedG16(src[0]); - dst[2] = SkGetPackedB16(src[0]); - src++; + for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { + dst[0] = SkGetPackedR16(src[x]); + dst[1] = SkGetPackedG16(src[x]); + dst[2] = SkGetPackedB16(src[x]); dst += 3; } } break; } case SkBitmap::kARGB_8888_Config: { - const int width = bitmap.width(); - const int rowBytes = width * 3; - result = new SkMemoryStream(rowBytes * bitmap.height()); + const int rowBytes = srcRect.width() * 3; + result = new SkMemoryStream(rowBytes * srcRect.height()); uint8_t* dst = (uint8_t*)result->getMemoryBase(); - for (int y = 0; y < bitmap.height(); y++) { + for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint32_t* src = bitmap.getAddr32(0, y); - for (int x = 0; x < width; x++) { - dst[0] = SkGetPackedR32(src[0]); - dst[1] = SkGetPackedG32(src[0]); - dst[2] = SkGetPackedB32(src[0]); - src++; + for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { + dst[0] = SkGetPackedR32(src[x]); + dst[1] = SkGetPackedG32(src[x]); + dst[2] = SkGetPackedB32(src[x]); dst += 3; } } @@ -149,7 +153,8 @@ SkPDFArray* makeIndexedColorSpace(SkColorTable* table) { }; // namespace -SkPDFImage::SkPDFImage(const SkBitmap& bitmap, const SkPaint& paint) { +SkPDFImage::SkPDFImage(const SkBitmap& bitmap, const SkIRect& srcRect, + const SkPaint& paint) { SkBitmap::Config config = bitmap.getConfig(); // TODO(vandebo) Handle alpha and alpha only images correctly. @@ -159,7 +164,7 @@ SkPDFImage::SkPDFImage(const SkBitmap& bitmap, const SkPaint& paint) { config == SkBitmap::kIndex8_Config || config == SkBitmap::kRLE_Index8_Config); - SkMemoryStream* image_data = extractImageData(bitmap); + SkMemoryStream* image_data = extractImageData(bitmap, srcRect); SkAutoUnref image_data_unref(image_data); fStream = new SkPDFStream(image_data); fStream->unref(); // SkRefPtr and new both took a reference. @@ -172,11 +177,11 @@ SkPDFImage::SkPDFImage(const SkBitmap& bitmap, const SkPaint& paint) { subTypeValue->unref(); // SkRefPtr and new both took a reference. insert("Subtype", subTypeValue.get()); - SkRefPtr widthValue = new SkPDFInt(bitmap.width()); + SkRefPtr widthValue = new SkPDFInt(srcRect.width()); widthValue->unref(); // SkRefPtr and new both took a reference. insert("Width", widthValue.get()); - SkRefPtr heightValue = new SkPDFInt(bitmap.height()); + SkRefPtr heightValue = new SkPDFInt(srcRect.height()); heightValue->unref(); // SkRefPtr and new both took a reference. insert("Height", heightValue.get()); -- 2.7.4