[poppler] poppler/CairoOutputDev.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 26 18:01:11 UTC 2023


 poppler/CairoOutputDev.cc |   47 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 42 insertions(+), 5 deletions(-)

New commits:
commit 1327646900994c033155100adf7bbaad7654ff50
Author: Artemy Gordon <artemy.gordon at gmail.com>
Date:   Thu Jan 26 18:01:09 2023 +0000

    Add handling matte entry in cairo backend

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


More information about the poppler mailing list