[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
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 @@
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 @@
* @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::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::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::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 @@
}; // 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 @@
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 @@
subTypeValue->unref(); // SkRefPtr and new both took a reference.
insert("Subtype", subTypeValue.get());
- SkRefPtr<SkPDFInt> widthValue = new SkPDFInt(bitmap.width());
+ SkRefPtr<SkPDFInt> widthValue = new SkPDFInt(srcRect.width());
widthValue->unref(); // SkRefPtr and new both took a reference.
insert("Width", widthValue.get());
- SkRefPtr<SkPDFInt> heightValue = new SkPDFInt(bitmap.height());
+ SkRefPtr<SkPDFInt> heightValue = new SkPDFInt(srcRect.height());
heightValue->unref(); // SkRefPtr and new both took a reference.
insert("Height", heightValue.get());