//======================================================================== // // MarkedContentOutputDev.h // // This file is licensed under the GPLv2 or later // // Copyright 2013 Igalia S.L. // Copyright 2018-2021 Albert Astals Cid // Copyright 2021 Adrian Johnson // Copyright 2022 Oliver Sander // //======================================================================== #ifndef MARKEDCONTENTOUTPUTDEV_H #define MARKEDCONTENTOUTPUTDEV_H #include "goo/gmem.h" #include "poppler_private_export.h" #include "OutputDev.h" #include "GfxState.h" #include "GfxFont.h" #include class Dict; class UnicodeMap; class TextSpan { public: TextSpan(const TextSpan &other) : data(other.data) { data->refcount++; } TextSpan &operator=(const TextSpan &other) { if (this != &other) { data = other.data; data->refcount++; } return *this; } ~TextSpan() { if (data && --data->refcount == 0) { delete data; } } const std::shared_ptr &getFont() const { return data->font; } GooString *getText() const { return data->text; } GfxRGB &getColor() const { return data->color; } private: // Note: Takes ownership of strings, increases refcount for font. TextSpan(GooString *text, std::shared_ptr font, const GfxRGB color) : data(new Data) { data->text = text; data->font = std::move(font); data->color = color; } struct Data { std::shared_ptr font; GooString *text; GfxRGB color; unsigned refcount; Data() : refcount(1) { } ~Data() { assert(refcount == 0); delete text; } Data(const Data &) = delete; Data &operator=(const Data &) = delete; }; Data *data; friend class MarkedContentOutputDev; }; typedef std::vector TextSpanArray; class POPPLER_PRIVATE_EXPORT MarkedContentOutputDev : public OutputDev { public: explicit MarkedContentOutputDev(int mcidA, const Object &stmObj); ~MarkedContentOutputDev() override; virtual bool isOk() { return true; } bool upsideDown() override { return true; } bool useDrawChar() override { return true; } bool interpretType3Chars() override { return false; } bool needNonText() override { return false; } bool needCharCount() override { return false; } void startPage(int pageNum, GfxState *state, XRef *xref) override; void endPage() override; void beginForm(Ref id) override; void endForm(Ref id) override; void drawChar(GfxState *state, double xx, double yy, double dx, double dy, double ox, double oy, CharCode c, int nBytes, const Unicode *u, int uLen) override; void beginMarkedContent(const char *name, Dict *properties) override; void endMarkedContent(GfxState *state) override; const TextSpanArray &getTextSpans() const; private: void endSpan(); bool inMarkedContent() const { return mcidStack.size() > 0; } bool contentStreamMatch(); bool needFontChange(const std::shared_ptr &font) const; std::shared_ptr currentFont; GooString *currentText; GfxRGB currentColor; TextSpanArray textSpans; int mcid; std::vector mcidStack; std::vector formStack; double pageWidth; double pageHeight; const UnicodeMap *unicodeMap; Object stmRef; }; #endif /* !MARKEDCONTENTOUTPUTDEV_H */