Commit 3c287945 authored by Mahmoud Khalil's avatar Mahmoud Khalil
Browse files

Adds support for transparency as well as improvements to AnnotStamp

parent d08d596c
Pipeline #364381 failed with stage
in 8 minutes and 2 seconds
......@@ -5377,26 +5377,8 @@ void AnnotStamp::initialize(PDFDoc *docA, Dict *dict)
customImageRef = Ref::INVALID();
}
void AnnotStamp::setIcon(GooString *new_icon)
{
if (new_icon) {
icon = std::make_unique<GooString>(new_icon);
} else {
icon = std::make_unique<GooString>();
}
update("Name", Object(objName, icon->c_str()));
invalidateAppearance();
}
void AnnotStamp::setCustomImage(ImageXObject *img)
void AnnotStamp::generateStampAppearance()
{
if (!img)
return;
clearCustomImage();
customImageRef = img->getRef();
std::string imgStrName = "X" + std::to_string(customImageRef.num);
GooString imgRefName(imgStrName);
......@@ -5416,11 +5398,56 @@ void AnnotStamp::setCustomImage(ImageXObject *img)
double bboxArray[4] = { 0, 0, rect->x2 - rect->x1, rect->y2 - rect->y1 };
const GooString *appearBuf = appearBuilder.buffer();
appearance = createForm(appearBuf, bboxArray, false, resDict);
}
void AnnotStamp::draw(Gfx *gfx, bool printing)
{
if (!isVisible(printing))
return;
annotLocker();
if (appearance.isNull()) {
if (customImageRef == Ref::INVALID())
return;
generateStampAppearance();
}
// draw the appearance stream
Object obj = appearance.fetch(gfx->getXRef());
if (appearBBox) {
gfx->drawAnnot(&obj, nullptr, color.get(), appearBBox->getPageXMin(), appearBBox->getPageYMin(), appearBBox->getPageXMax(), appearBBox->getPageYMax(), getRotation());
} else {
gfx->drawAnnot(&obj, nullptr, color.get(), rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
}
}
void AnnotStamp::setIcon(GooString *new_icon)
{
if (new_icon) {
icon = std::make_unique<GooString>(new_icon);
} else {
icon = std::make_unique<GooString>();
}
update("Name", Object(objName, icon->c_str()));
invalidateAppearance();
}
void AnnotStamp::setCustomImage(ImageXObject *img)
{
if (!img)
return;
annotLocker();
clearCustomImage();
customImageRef = img->getRef();
generateStampAppearance();
Ref updatedAppearanceStream = doc->getXRef()->addIndirectObject(&appearance);
Object obj1 = Object(new Dict(doc->getXRef()));
obj1.dictAdd("N", Object(updatedAppearanceStream));
invalidateAppearance();
update("AP", std::move(obj1));
}
......
......@@ -1194,6 +1194,8 @@ public:
AnnotStamp(PDFDoc *docA, Object &&dictObject, const Object *obj);
~AnnotStamp() override;
void draw(Gfx *gfx, bool printing) override;
void setIcon(GooString *new_icon);
void setCustomImage(ImageXObject *img);
......@@ -1205,6 +1207,7 @@ public:
private:
void initialize(PDFDoc *docA, Dict *dict);
void generateStampAppearance();
std::unique_ptr<GooString> icon; // Name (Default Draft)
Ref customImageRef;
......
......@@ -16,9 +16,26 @@
#include "Stream.h"
#include "Dict.h"
#include <iostream>
#define imgLocker() std::unique_lock<std::recursive_mutex> locker(mutex)
ImageXObject::ImageXObject(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength)
{
initialize(docA, widthA, heightA, colorSpace, bitsPerComponent, data, dataLength);
}
ImageXObject::ImageXObject(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength, Object &&sMaskObj)
{
initialize(docA, widthA, heightA, colorSpace, bitsPerComponent, data, dataLength);
imgLocker();
Dict *dict = imgObj.streamGetDict();
dict->add("SMask", std::move(sMaskObj));
doc->getXRef()->setModifiedObject(&imgObj, ref);
}
void ImageXObject::initialize(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength)
{
doc = docA;
width = widthA;
......
......@@ -11,6 +11,8 @@
#ifndef IMAGEXOBJECT_H
#define IMAGEXOBJECT_H
#include <mutex>
#include "Object.h"
class PDFDoc;
......@@ -26,6 +28,7 @@ class POPPLER_PRIVATE_EXPORT ImageXObject
{
public:
ImageXObject(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength);
ImageXObject(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength, Object &&sMaskObj);
~ImageXObject() { }
void setPage(int pageA);
......@@ -35,7 +38,11 @@ public:
int getWidth() const { return width; }
int getHeight() const { return height; }
Object &getImageXObjectObject() { return imgObj; }
private:
void initialize(PDFDoc *docA, int widthA, int heightA, ColorSpace colorSpace, int bitsPerComponent, char *data, int dataLength);
PDFDoc *doc;
Object imgObj;
......@@ -45,6 +52,8 @@ private:
int width;
int height;
mutable std::recursive_mutex mutex;
};
#endif
......@@ -41,7 +41,7 @@ namespace Poppler {
class DocumentData;
PDFRectangle boundaryToPdfRectangle(::Page *pdfPage, const QRectF &r, int flags);
void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data);
void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data, QByteArray *sMaskData);
class AnnotationPrivate : public QSharedData
{
......
......@@ -138,6 +138,7 @@ ImageXObject *AnnotationPrivate::convertQImageToImageXObject(const QImage &qimg)
QImage convertedQImage = qimg;
QByteArray *data = new QByteArray();
QByteArray *sMaskData = new QByteArray();
int width = convertedQImage.width();
int height = convertedQImage.height();
int bitsPerComponent = 1;
......@@ -211,16 +212,23 @@ ImageXObject *AnnotationPrivate::convertQImageToImageXObject(const QImage &qimg)
break;
}
getRawDataFromQImage(convertedQImage, convertedQImage.depth(), data);
getRawDataFromQImage(convertedQImage, convertedQImage.depth(), data, sMaskData);
ImageXObject *imgXObject = new ImageXObject(parentDoc->doc, width, height, colorSpace, bitsPerComponent, data->data(), data->count());
ImageXObject *imgXObject;
if (sMaskData->count() > 0) {
ImageXObject sMaskImgXObject(parentDoc->doc, width, height, ColorSpace::DeviceGray, 8, sMaskData->data(), sMaskData->count());
imgXObject = new ImageXObject(parentDoc->doc, width, height, colorSpace, bitsPerComponent, data->data(), data->count(), std::move(sMaskImgXObject.getImageXObjectObject()));
} else {
imgXObject = new ImageXObject(parentDoc->doc, width, height, colorSpace, bitsPerComponent, data->data(), data->count());
}
delete data;
return imgXObject;
}
void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data)
void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data, QByteArray *sMaskData)
{
int height = qimg.height();
int width = qimg.width();
......@@ -246,6 +254,7 @@ void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data
for (int line = 0; line < height; line++) {
const QRgb *lineData = reinterpret_cast<const QRgb *>(qimg.scanLine(line));
for (int offset = 0; offset < width; offset++) {
char a = (char)qAlpha(lineData[offset]);
char r = (char)qRed(lineData[offset]);
char g = (char)qGreen(lineData[offset]);
char b = (char)qBlue(lineData[offset]);
......@@ -253,6 +262,8 @@ void getRawDataFromQImage(const QImage &qimg, int bitsPerPixel, QByteArray *data
data->append(r);
data->append(g);
data->append(b);
sMaskData->append(a);
}
}
break;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment