diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp deleted file mode 100644 index 6368d979756..00000000000 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PdfSpecialHandler.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/************************************************************************* -** PdfSpecialHandler.cpp ** -** ** -** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2021 Martin Gieseking <martin.gieseking@uos.de> ** -** ** -** This program is free software; you can redistribute it and/or ** -** modify it under the terms of the GNU General Public License as ** -** published by the Free Software Foundation; either version 3 of ** -** the License, or (at your option) any later version. ** -** ** -** This program is distributed in the hope that it will be useful, but ** -** WITHOUT ANY WARRANTY; without even the implied warranty of ** -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** -** GNU General Public License for more details. ** -** ** -** You should have received a copy of the GNU General Public License ** -** along with this program; if not, see <http://www.gnu.org/licenses/>. ** -*************************************************************************/ - -#include <array> -#include <cstring> -#include <unordered_map> -#include <utility> -#include "Color.hpp" -#include "HyperlinkManager.hpp" -#include "InputReader.hpp" -#include "MapLine.hpp" -#include "PdfSpecialHandler.hpp" -#include "FontMap.hpp" -#include "Message.hpp" -#include "PapersizeSpecialHandler.hpp" -#include "PDFParser.hpp" -#include "SpecialActions.hpp" -#include "SpecialManager.hpp" - -using namespace std; - -using CmdHandler = void (PdfSpecialHandler::*)(StreamInputReader&, SpecialActions&); - - -void PdfSpecialHandler::preprocess (const string&, istream &is, SpecialActions &actions) { - StreamInputReader ir(is); - ir.skipSpace(); - const string cmdstr = ir.getWord(); - static unordered_map<string, CmdHandler> commands = { - {"bann", &PdfSpecialHandler::preprocessBeginAnn}, - {"bannot", &PdfSpecialHandler::preprocessBeginAnn}, - {"beginann", &PdfSpecialHandler::preprocessBeginAnn}, - {"dest", &PdfSpecialHandler::preprocessDest}, - {"pagesize", &PdfSpecialHandler::preprocessPagesize}, - {"mapfile", &PdfSpecialHandler::preprocessMapfile}, - {"mapline", &PdfSpecialHandler::preprocessMapline} - }; - auto it = commands.find(cmdstr); - if (it != commands.end()) - (this->*it->second)(ir, actions); -} - - -bool PdfSpecialHandler::process (const string&, istream &is, SpecialActions &actions) { - _active = true; - StreamInputReader ir(is); - ir.skipSpace(); - const string cmdstr = ir.getWord(); - ir.skipSpace(); - // dvipdfm(x) specials currently supported - static unordered_map<string, CmdHandler> commands = { - {"bann", &PdfSpecialHandler::processBeginAnn}, - {"bannot", &PdfSpecialHandler::processBeginAnn}, - {"beginann", &PdfSpecialHandler::processBeginAnn}, - {"eann", &PdfSpecialHandler::processEndAnn}, - {"eannot", &PdfSpecialHandler::processEndAnn}, - {"endann", &PdfSpecialHandler::processEndAnn}, - {"dest", &PdfSpecialHandler::processDest}, - }; - auto it = commands.find(cmdstr); - if (it != commands.end()) - (this->*it->second)(ir, actions); - return true; -} - - -static char prepare_mode (InputReader &ir) { - // read mode selector ('+', '-', or '=') - char modechar = '+'; // default mode (append if new, do not replace existing mapping) - if (strchr("=+-", ir.peek())) // leading modifier given? - modechar = static_cast<char>(ir.get()); - return modechar; -} - - -/** Sets the page size. This command is similar to the papersize special. - * Syntax pdf:pagesize (<dimname> <dimlenhth>)+ */ -void PdfSpecialHandler::preprocessPagesize (StreamInputReader &ir, SpecialActions &actions) { - // add page sizes to collection of paper sizes in order to handle them equally - SpecialHandler *handler = SpecialManager::instance().findHandlerByName("papersize"); - if (auto papersizeHandler = dynamic_cast<PapersizeSpecialHandler*>(handler)) { - try { - Length width, height; - // parse parameter sequence of the form (name length)+ - while (!ir.eof()) { - string dimname = ir.getWord(); - string lenstr = ir.getString(" \t"); - // only consider width and height settings - if (dimname == "width" && !lenstr.empty()) - width.set(lenstr); - else if (dimname == "height" && !lenstr.empty()) - height.set(lenstr); - } - papersizeHandler->storePaperSize(actions.getCurrentPageNumber(), width, height); - } - catch (UnitException &e) { // ignore invalid length units for now - } - } -} - - -void PdfSpecialHandler::preprocessMapfile (StreamInputReader &ir, SpecialActions&) { - char modechar = prepare_mode(ir); - string fname = ir.getString(); - if (!FontMap::instance().read(fname, modechar)) - Message::wstream(true) << "can't open map file " << fname << '\n'; -} - - -void PdfSpecialHandler::preprocessMapline (StreamInputReader &ir, SpecialActions&) { - char modechar = prepare_mode(ir); - try { - MapLine mapline(ir.getStream()); - FontMap::instance().apply(mapline, modechar); - } - catch (const MapLineException &ex) { - Message::wstream(true) << "pdf:mapline: " << ex.what() << '\n'; - } -} - - -/** Defines a named destination, e.g. a link target. - * Syntax: dest PDFString PDFDest */ -void PdfSpecialHandler::preprocessDest (StreamInputReader &ir, SpecialActions &actions) { - PDFParser parser; - vector<PDFObject> objects = parser.parse(ir, [&](const string &opname, vector<PDFObject> &objects) { - if (!opname.empty() && opname[0] == '@') { - if (opname == "@thispage") - objects.emplace_back(static_cast<int>(actions.getCurrentPageNumber())); - else if (opname == "@xpos") - objects.emplace_back(actions.getX()); - else if (opname == "@ypos") - objects.emplace_back(actions.getY()); - } - }); - if (objects.size() < 2) - return; - auto name = objects[0].get<string>(); - auto dest = objects[1].get<PDFArray>(); - // get target info from array [pageno /XYZ xpos ypos zpos] - if (name && dest && dest->size() >= 4 && dest->at(0).get<int>()) { - int pageno = *dest->at(0).get<int>(); - HyperlinkManager::instance().addNameAchor(*name, pageno); - } -} - - -/** Extracts the URI from a PDF annotation dictionary. "GoTo" targets (named anchors) - * are prefixed with a '#'. - * @param[in] annotDict annotation dictionary containing the target URI - * @return the URI if one was found, "" otherwise */ -static string get_uri (const PDFDict &annotDict) { - // At the moment, we only support link annotations - const PDFObject *type = annotDict.get("Type"); - if (type && string(*type) == "Annot") { - const PDFObject *subtype = annotDict.get("Subtype"); - if (subtype && string(*subtype) == "Link") { - const PDFObject *dict = annotDict.get("A"); - if (const PDFDict *actionDict = dict->get<PDFDict>()) { - if (const PDFObject *s = actionDict->get("S")) { - if (string(*s) == "GoTo") { - if (const PDFObject *dest = actionDict->get("D")) - return "#" + string(*dest); - } - else if (string(*s) == "URI") { - if (const PDFObject *uri = actionDict->get("URI")) - return string(*uri); - } - } - } - } - } - return ""; -} - - -void PdfSpecialHandler::preprocessBeginAnn (StreamInputReader &ir, SpecialActions&) { - PDFParser parser; - vector<PDFObject> pdfobjs = parser.parse(ir); - if (pdfobjs.empty() || !pdfobjs[0].get<PDFDict>()) - return; - const PDFDict &annotDict = *pdfobjs[0].get<PDFDict>(); - string uri = get_uri(annotDict); - if (!uri.empty()) - HyperlinkManager::instance().addHrefAnchor(uri); -} - - -/** Converts a PDFObject to a Color, where a single number denotes a gray value. - * Number arrays are treated as gray, RGB, or CMYK colors depending on the - * number of components. */ -static Color to_color (const PDFObject &obj) { - Color color; - if (obj.get<int>() || obj.get<double>()) - color.setGray(double(obj)); - else if (auto colorArray = obj.get<PDFArray>()) { - size_t size = min(size_t(4), colorArray->size()); - valarray<double> colorComps(size); - for (size_t i=0; i < size; i++) - colorComps[i] = double(colorArray->at(i)); - switch (size) { - case 1: color.setGray(colorComps); break; - case 3: color.setRGB(colorComps); break; - case 4: color.setCMYK(colorComps); break; - } - } - return color; -} - - -/** Begins a breakable annotation, e.g. a hyperlink. - * Syntax: beginann PDFDict */ -void PdfSpecialHandler::processBeginAnn (StreamInputReader &ir, SpecialActions &actions) { - PDFParser parser; - vector<PDFObject> pdfobjs = parser.parse(ir); - if (pdfobjs.empty() || !pdfobjs[0].get<PDFDict>()) - return; - const PDFDict &annotDict = *pdfobjs[0].get<PDFDict>(); - string uri = get_uri(annotDict); - if (uri.empty()) - return; - - // check presence of entry /Border [hr vr bw] defining the horizontal/vertical - // corner radius and the border width - auto it = annotDict.find("Border"); - if (it != annotDict.end() && it->second.get<PDFArray>() && it->second.get<PDFArray>()->size() > 2) - HyperlinkManager::instance().setLineWidth(double(it->second.get<PDFArray>()->at(2))); - - // check presence of entry /C defining the border color - it = annotDict.find("C"); - if (it != annotDict.end()) - HyperlinkManager::setDefaultLinkColor(to_color(it->second)); - HyperlinkManager::instance().createLink(uri, actions); -} - - -/** Terminates the preceding breakable annotation. - * Syntax: endann */ -void PdfSpecialHandler::processEndAnn (StreamInputReader&, SpecialActions &actions) { - HyperlinkManager::instance().closeAnchor(actions); -} - - -void PdfSpecialHandler::processDest (StreamInputReader &ir, SpecialActions &actions) { - PDFParser parser; - vector<PDFObject> objects = parser.parse(ir); - if (!objects.empty()) { - if (auto name = objects[0].get<string>()) - HyperlinkManager::instance().setActiveNameAnchor(*name, actions); - } -} - - -/** This method is called every time the DVI position changes. */ -void PdfSpecialHandler::dviMovedTo (double x, double y, SpecialActions &actions) { - if (_active) - HyperlinkManager::instance().checkNewLine(actions); -} - - -void PdfSpecialHandler::dviEndPage (unsigned pageno, SpecialActions &actions) { - if (_active) { - HyperlinkManager::instance().createViews(pageno, actions); - _active = false; - } -} - - -vector<const char*> PdfSpecialHandler::prefixes() const { - vector<const char*> pfx {"pdf:"}; - return pfx; -} |