summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--poppler/CairoOutputDev.cc47
1 files changed, 42 insertions, 5 deletions
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 946cb1a4..2c0e0672 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -2763,12 +2763,35 @@ cleanup:
delete imgStr;
}
+static inline void getMatteColorRgb(GfxImageColorMap *colorMap, const GfxColor *matteColorIn, GfxRGB *matteColorRgb)
+{
+ colorMap->getColorSpace()->getRGB(matteColorIn, matteColorRgb);
+ matteColorRgb->r = colToByte(matteColorRgb->r);
+ matteColorRgb->g = colToByte(matteColorRgb->g);
+ matteColorRgb->b = colToByte(matteColorRgb->b);
+}
+
+static inline void applyMask(unsigned int *imagePointer, int length, GfxRGB matteColor, unsigned char *alphaPointer)
+{
+ unsigned char *p, r, g, b;
+ int i;
+
+ for (i = 0, p = (unsigned char *)imagePointer; i < length; i++, p += 4, alphaPointer++) {
+ if (*alphaPointer) {
+ b = std::clamp(matteColor.b + (int)(p[0] - matteColor.b) * 255 / *alphaPointer, 0, 255);
+ g = std::clamp(matteColor.g + (int)(p[1] - matteColor.g) * 255 / *alphaPointer, 0, 255);
+ r = std::clamp(matteColor.r + (int)(p[2] - matteColor.r) * 255 / *alphaPointer, 0, 255);
+ imagePointer[i] = (r << 16) | (g << 8) | (b << 0);
+ }
+ }
+}
+
// XXX: is this affect by AIS(alpha is shape)?
void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GfxImageColorMap *maskColorMap,
bool maskInterpolate)
{
ImageStream *maskImgStr, *imgStr;
- ptrdiff_t row_stride;
+ ptrdiff_t row_stride, mask_row_stride;
unsigned char *maskBuffer, *buffer;
unsigned char *maskDest;
unsigned int *dest;
@@ -2779,6 +2802,12 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
int y;
cairo_filter_t filter;
cairo_filter_t maskFilter;
+ GfxRGB matteColorRgb;
+
+ const GfxColor *matteColor = maskColorMap->getMatteColor();
+ if (matteColor != nullptr) {
+ getMatteColorRgb(colorMap, matteColor, &matteColorRgb);
+ }
maskImgStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits());
maskImgStr->reset();
@@ -2791,9 +2820,9 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
}
maskBuffer = cairo_image_surface_get_data(maskImage);
- row_stride = cairo_image_surface_get_stride(maskImage);
+ mask_row_stride = cairo_image_surface_get_stride(maskImage);
for (y = 0; y < maskHeight; y++) {
- maskDest = (unsigned char *)(maskBuffer + y * row_stride);
+ maskDest = (unsigned char *)(maskBuffer + y * mask_row_stride);
pix = maskImgStr->getLine();
if (likely(pix != nullptr)) {
maskColorMap->getGrayLine(pix, maskDest, maskWidth);
@@ -2835,14 +2864,22 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s
for (y = 0; y < height; y++) {
dest = reinterpret_cast<unsigned int *>(buffer + y * row_stride);
pix = imgStr->getLine();
- colorMap->getRGBLine(pix, dest, width);
+ if (likely(pix != nullptr)) {
+ colorMap->getRGBLine(pix, dest, width);
+ if (matteColor != nullptr) {
+ maskDest = (unsigned char *)(maskBuffer + y * mask_row_stride);
+ applyMask(dest, width, matteColorRgb, maskDest);
+ }
+ }
}
filter = getFilterForSurface(image, interpolate);
cairo_surface_mark_dirty(image);
- setMimeData(state, str, ref, colorMap, image, height);
+ if (matteColor == nullptr) {
+ setMimeData(state, str, ref, colorMap, image, height);
+ }
pattern = cairo_pattern_create_for_surface(image);
cairo_surface_destroy(image);