From 2c5490a061d169145383b6e68eac6eac8650177a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Sep 2023 21:25:35 +0530 Subject: [PATCH] PDF Output: Fix background image + text not rendering correctly if the same background image is used with different text multiple times. Fixes #2035338 [conversion from epub to pdf - all chapter titles are the same as the first chapter](https://bugs.launchpad.net/calibre/+bug/2035338) Chromium renders this as the background image with a soft mask. The background image is duplicated, however calibre's image dedup cannot work as the softmask is part of the image dictionary and dedup works by replacing references to the image dictionary. There is a similar breakage which will happen if there are duplicated soft masks as the dedup code does not currently update the softmask references. --- src/calibre/utils/podofo/images.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/calibre/utils/podofo/images.cpp b/src/calibre/utils/podofo/images.cpp index 6e9b6029f9..1ee3aa66c4 100644 --- a/src/calibre/utils/podofo/images.cpp +++ b/src/calibre/utils/podofo/images.cpp @@ -13,9 +13,11 @@ class Image { charbuff buf; int64_t width, height; PdfReference ref; + PdfReference smask; + bool is_valid; + Image( const Image & ) ; Image & operator=( const Image & ) ; - bool is_valid; public: Image(const PdfReference &reference, const PdfObject *o) : buf(), width(0), height(0), ref(reference) { @@ -30,18 +32,20 @@ class Image { const PdfDictionary &dict = o->GetDictionary(); if (dict.HasKey("Width") && dict.GetKey("Width")->IsNumber()) width = dict.GetKey("Width")->GetNumber(); if (dict.HasKey("Height") && dict.GetKey("Height")->IsNumber()) height = dict.GetKey("Height")->GetNumber(); + if (dict.HasKey("SMask") && dict.GetKey("SMask")->IsReference()) smask = dict.GetKey("SMask")->GetReference(); } Image(Image &&other) noexcept : - buf(std::move(other.buf)), width(other.width), height(other.height), ref(other.ref) { + buf(std::move(other.buf)), width(other.width), height(other.height), ref(other.ref), smask(other.smask) { other.buf = charbuff(); is_valid = other.is_valid; } Image& operator=(Image &&other) noexcept { buf = std::move(other.buf); other.buf = charbuff(); ref = other.ref; width = other.width; height = other.height; is_valid = other.is_valid; + smask = other.smask; return *this; } bool operator==(const Image &other) const noexcept { - return other.width == width && is_valid && other.is_valid && other.height == height && other.buf == buf; + return other.width == width && is_valid && other.is_valid && other.height == height && other.smask == smask && other.buf == buf; } std::size_t hash() const noexcept { return buf.size(); } const PdfReference& reference() const noexcept { return ref; }