Index: experimental/PdfViewer/SkPdfRenderer.cpp |
=================================================================== |
--- experimental/PdfViewer/SkPdfRenderer.cpp (revision 10523) |
+++ experimental/PdfViewer/SkPdfRenderer.cpp (working copy) |
@@ -435,11 +435,11 @@ |
return grayColortable; |
} |
-static SkBitmap transferImageStreamToBitmap(const unsigned char* uncompressedStream, size_t uncompressedStreamLength, |
+static SkBitmap* transferImageStreamToBitmap(const unsigned char* uncompressedStream, size_t uncompressedStreamLength, |
int width, int height, int bytesPerLine, |
int bpc, const std::string& colorSpace, |
bool transparencyMask) { |
- SkBitmap bitmap; |
+ SkBitmap* bitmap = new SkBitmap(); |
//int components = GetColorSpaceComponents(colorSpace); |
//#define MAX_COMPONENTS 10 |
@@ -462,8 +462,8 @@ |
uncompressedStream += bytesPerLine; |
} |
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); |
- bitmap.setPixels(uncompressedStreamArgb); |
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); |
+ bitmap->setPixels(uncompressedStreamArgb); |
} |
else if ((colorSpace == "DeviceGray" || colorSpace == "Gray") && bpc == 8) { |
unsigned char* uncompressedStreamA8 = (unsigned char*)malloc(width * height); |
@@ -478,9 +478,9 @@ |
uncompressedStream += bytesPerLine; |
} |
- bitmap.setConfig(transparencyMask ? SkBitmap::kA8_Config : SkBitmap::kIndex8_Config, |
+ bitmap->setConfig(transparencyMask ? SkBitmap::kA8_Config : SkBitmap::kIndex8_Config, |
width, height); |
- bitmap.setPixels(uncompressedStreamA8, transparencyMask ? NULL : getGrayColortable()); |
+ bitmap->setPixels(uncompressedStreamA8, transparencyMask ? NULL : getGrayColortable()); |
} |
// TODO(edisonn): Report Warning, NYI, or error |
@@ -496,10 +496,10 @@ |
// this functions returns the image, it does not look at the smask. |
-static SkBitmap getImageFromObject(PdfContext* pdfContext, SkPdfImageDictionary* image, bool transparencyMask) { |
+static SkBitmap* getImageFromObjectCore(PdfContext* pdfContext, SkPdfImageDictionary* image, bool transparencyMask) { |
if (image == NULL || !image->hasStream()) { |
// TODO(edisonn): report warning to be used in testing. |
- return SkBitmap(); |
+ return NULL; |
} |
int64_t bpc = image->BitsPerComponent(pdfContext->fPdfDoc); |
@@ -507,9 +507,37 @@ |
int64_t height = image->Height(pdfContext->fPdfDoc); |
std::string colorSpace = "DeviceRGB"; |
+ bool indexed = false; |
+ SkPMColor colors[256]; |
+ int cnt = 0; |
+ |
// TODO(edisonn): color space can be an array too! |
if (image->isColorSpaceAName(pdfContext->fPdfDoc)) { |
colorSpace = image->getColorSpaceAsName(pdfContext->fPdfDoc); |
+ } else if (image->isColorSpaceAArray(pdfContext->fPdfDoc)) { |
+ SkPdfArray* array = image->getColorSpaceAsArray(pdfContext->fPdfDoc); |
+ if (array && array->size() == 4 && array->objAtAIndex(0)->isName("Indexed") && |
+ (array->objAtAIndex(1)->isName("DeviceRGB") || array->objAtAIndex(1)->isName("RGB")) && |
+ array->objAtAIndex(2)->isInteger() && |
+ array->objAtAIndex(3)->isHexString() |
+ ) { |
+ // TODO(edisonn): suport only DeviceRGB for now. |
+ indexed = true; |
+ cnt = array->objAtAIndex(2)->intValue() + 1; |
+ if (cnt > 256) { |
+ // TODO(edionn): report NYIs |
+ return NULL; |
+ } |
+ SkColorTable colorTable(cnt); |
+ NotOwnedString data = array->objAtAIndex(3)->strRef(); |
+ if (data.fBytes != (unsigned int)cnt * 3) { |
+ // TODO(edionn): report error/warning |
+ return NULL; |
+ } |
+ for (int i = 0 ; i < cnt; i++) { |
+ colors[i] = SkPreMultiplyARGB(0xff, data.fBuffer[3 * i], data.fBuffer[3 * i + 1], data.fBuffer[3 * i + 2]); |
+ } |
+ } |
} |
/* |
@@ -532,7 +560,7 @@ |
if (!stream || !stream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength) || |
uncompressedStream == NULL || uncompressedStreamLength == 0) { |
// TODO(edisonn): report warning to be used in testing. |
- return SkBitmap(); |
+ return NULL; |
} |
SkPdfStreamCommonDictionary* streamDict = (SkPdfStreamCommonDictionary*)stream; |
@@ -543,8 +571,8 @@ |
streamDict->getFilterAsArray(NULL)->size() > 0 && |
streamDict->getFilterAsArray(NULL)->objAtAIndex(0)->isName() && |
streamDict->getFilterAsArray(NULL)->objAtAIndex(0)->nameValue2() == "DCTDecode"))) { |
- SkBitmap bitmap; |
- SkImageDecoder::DecodeMemory(uncompressedStream, uncompressedStreamLength, &bitmap); |
+ SkBitmap* bitmap = new SkBitmap(); |
+ SkImageDecoder::DecodeMemory(uncompressedStream, uncompressedStreamLength, bitmap); |
return bitmap; |
} |
@@ -562,6 +590,15 @@ |
// SkImageDecoder::Factory() |
// } |
+ // TODO(edisonn): assumes RGB for now, since it is the only onwe implemented |
+ if (indexed) { |
+ SkBitmap* bitmap = new SkBitmap(); |
+ bitmap->setConfig(SkBitmap::kIndex8_Config, width, height); |
+ SkColorTable* colorTable = new SkColorTable(colors, cnt); |
+ bitmap->setPixels((void*)uncompressedStream, colorTable); |
+ return bitmap; |
+ } |
+ |
int bytesPerLine = (int)(uncompressedStreamLength / height); |
#ifdef PDF_TRACE |
if (uncompressedStreamLength % height != 0) { |
@@ -569,7 +606,7 @@ |
} |
#endif |
- SkBitmap bitmap = transferImageStreamToBitmap( |
+ SkBitmap* bitmap = transferImageStreamToBitmap( |
(unsigned char*)uncompressedStream, uncompressedStreamLength, |
(int)width, (int)height, bytesPerLine, |
(int)bpc, colorSpace, |
@@ -578,7 +615,19 @@ |
return bitmap; |
} |
-static SkBitmap getSmaskFromObject(PdfContext* pdfContext, SkPdfImageDictionary* obj) { |
+static SkBitmap* getImageFromObject(PdfContext* pdfContext, SkPdfImageDictionary* image, bool transparencyMask) { |
+ if (!transparencyMask) { |
+ if (!image->hasData(SkPdfObject::kBitmap_Data)) { |
+ SkBitmap* bitmap = getImageFromObjectCore(pdfContext, image, transparencyMask); |
+ image->setData(bitmap, SkPdfObject::kBitmap_Data); |
+ } |
+ return (SkBitmap*) image->data(SkPdfObject::kBitmap_Data); |
+ } else { |
+ return getImageFromObjectCore(pdfContext, image, transparencyMask); |
+ } |
+} |
+ |
+static SkBitmap* getSmaskFromObject(PdfContext* pdfContext, SkPdfImageDictionary* obj) { |
SkPdfImageDictionary* sMask = obj->SMask(pdfContext->fPdfDoc); |
if (sMask) { |
@@ -594,8 +643,8 @@ |
return kIgnoreError_PdfResult; |
} |
- SkBitmap image = getImageFromObject(pdfContext, skpdfimage, false); |
- SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage); |
+ SkBitmap* image = getImageFromObject(pdfContext, skpdfimage, false); |
+ SkBitmap* sMask = getSmaskFromObject(pdfContext, skpdfimage); |
canvas->save(); |
canvas->setMatrix(pdfContext->fGraphicsState.fCTM); |
@@ -616,16 +665,16 @@ |
SkRect dst = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0), SkDoubleToScalar(1.0), SkDoubleToScalar(1.0)); |
// TODO(edisonn): soft mask type? alpha/luminosity. |
- if (sMask.empty()) { |
- canvas->drawBitmapRect(image, dst, NULL); |
+ if (!sMask || sMask->empty()) { |
+ canvas->drawBitmapRect(*image, dst, NULL); |
} else { |
canvas->saveLayer(&dst, NULL); |
- canvas->drawBitmapRect(image, dst, NULL); |
+ canvas->drawBitmapRect(*image, dst, NULL); |
SkPaint xfer; |
pdfContext->fGraphicsState.applyGraphicsState(&xfer, false); |
// TODO(edisonn): is the blend mode specified already implicitly/explicitly in pdf? |
xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_Mode |
- canvas->drawBitmapRect(sMask, dst, &xfer); |
+ canvas->drawBitmapRect(*sMask, dst, &xfer); |
canvas->restore(); |
} |
@@ -1255,15 +1304,20 @@ |
// TODO(edisonn): constants |
// TODO(edisonn): colored |
if (pattern->PaintType(pdfContext->fPdfDoc) == 1) { |
- int xStep = (int)pattern->XStep(pdfContext->fPdfDoc); |
- int yStep = (int)pattern->YStep(pdfContext->fPdfDoc); |
+ // TODO(edisonn): don't use abs, iterate as asked, if the cells intersect |
+ // it will change the result iterating in reverse |
+ int xStep = abs((int)pattern->XStep(pdfContext->fPdfDoc)); |
+ int yStep = abs((int)pattern->YStep(pdfContext->fPdfDoc)); |
SkRect bounds = path.getBounds(); |
+ |
+ // TODO(edisonn): xstep and ystep can be negative, and we need to iterate in reverse |
+ // TODO(edisonn): don't do that! |
+ bounds.sort(); |
+ |
SkScalar x; |
SkScalar y; |
- // TODO(edisonn): xstep and ystep can be negative, and we need to iterate in reverse |
- |
y = bounds.top(); |
int totalx = 0; |
int totaly = 0; |
@@ -1961,7 +2015,7 @@ |
void skpdfGraphicsStateApplySMask_name(PdfContext* pdfContext, const std::string& sMask) { |
if (sMask == "None") { |
pdfContext->fGraphicsState.fSoftMaskDictionary = NULL; |
- pdfContext->fGraphicsState.fSMask = SkBitmap(); |
+ pdfContext->fGraphicsState.fSMask = NULL; |
return; |
} |
@@ -1983,7 +2037,7 @@ |
} |
pdfContext->fGraphicsState.fSoftMaskDictionary = NULL; |
- pdfContext->fGraphicsState.fSMask = SkBitmap(); |
+ pdfContext->fGraphicsState.fSMask = NULL; |
skpdfGraphicsStateApplySMask_dict(pdfContext, obj->asDictionary()); |
} |