summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp670
1 files changed, 0 insertions, 670 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
deleted file mode 100644
index 05d87b89086..00000000000
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
+++ /dev/null
@@ -1,670 +0,0 @@
-/*************************************************************************
-** DVIReader.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 <algorithm>
-#include <sstream>
-#include "Color.hpp"
-#include "DVIActions.hpp"
-#include "DVIReader.hpp"
-#include "Font.hpp"
-#include "FontManager.hpp"
-#include "HashFunction.hpp"
-#include "JFM.hpp"
-#include "utility.hpp"
-#include "VectorStream.hpp"
-
-using namespace std;
-
-DVIReader::DVIReader (istream &is) : BasicDVIReader(is)
-{
- executePreamble();
- _bopOffsets = collectBopOffsets();
- // read data from postamble but don't process font definitions
- goToPostamble();
- executeCommand();
- executePostPost();
-}
-
-
-/** Executes all DVI commands read from the input stream. */
-void DVIReader::executeAll () {
- int opcode = 0;
- while (!eof() && opcode >= 0) {
- try {
- opcode = executeCommand();
- }
- catch (const InvalidDVIFileException &e) {
- // end of stream reached
- opcode = -1;
- }
- }
-}
-
-
-/** Reads and executes the commands of a single page.
- * This methods stops reading after the page's eop command has been executed.
- * @param[in] n number of page to be executed (1-based)
- * @returns true if page was read successfully */
-bool DVIReader::executePage (unsigned n) {
- clearStream(); // reset all status bits
- if (!isStreamValid())
- throw DVIException("invalid DVI file");
- if (n < 1 || n > numberOfPages())
- return false;
-
- seek(_bopOffsets[n-1]); // goto bop of n-th page
- _currPageNum = n;
- while (executeCommand() != OP_EOP);
- return true;
-}
-
-
-/** Computes a hash value for a given page. The hash algorithm is selected by
- * a HashFunction object which will also contain the resulting hash value if
- * this function returns true.
- * @param[in] pageno number of page to process (1-based)
- * @param[in,out] hashFunc hash function to use
- * @return true on success, hashFunc contains the resulting hash value */
-bool DVIReader::computePageHash (size_t pageno, HashFunction &hashFunc) {
- if (pageno == 0 || pageno > numberOfPages())
- return false;
-
- hashFunc.reset();
- clearStream();
- seek(_bopOffsets[pageno-1]+45); // now on first command after bop of selected page
- const size_t BUFSIZE = 4096;
- char buf[BUFSIZE];
- size_t numBytes = numberOfPageBytes(pageno-1)-46; // number of bytes excluding bop and eop
- while (numBytes > 0) {
- getInputStream().read(buf, min(numBytes, BUFSIZE));
- hashFunc.update(buf, getInputStream().gcount());
- numBytes -= getInputStream().gcount();
- }
- return true;
-}
-
-
-/////////////////////////////////////
-
-/** Reads and executes DVI preamble command.
- * Format: pre ver[1] num[4] den[4] mag[4] cmtlen[1] cmt[cmtlen] */
-void DVIReader::cmdPre (int) {
- uint8_t id = readUnsigned(1);
- setDVIVersion(DVIVersion(id)); // identification number
- uint32_t numer = readUnsigned(4); // numerator units of measurement
- uint32_t denom = readUnsigned(4); // denominator units of measurement
- if (denom == 0)
- throw DVIException("denominator of measurement unit is zero");
- _mag = readUnsigned(4); // magnification
- uint32_t k = readUnsigned(1); // length of following comment
- string comment = readString(k);
- // 1 dviunit * num/den == multiples of 0.0000001m
- // 1 dviunit * _dvibp: length of 1 dviunit in PS points * _mag/1000
- _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0;
- dviPre(id, numer, denom, _mag, comment);
-}
-
-
-/** Reads and executes DVI postamble command.
- * Format: post p[4] num[4] den[4] mag[4] ph[4] pw[4] sd[2] np[2] */
-void DVIReader::cmdPost (int) {
- uint32_t prevBopOffset = readUnsigned(4);
- uint32_t numer = readUnsigned(4);
- uint32_t denom = readUnsigned(4);
- if (denom == 0)
- throw DVIException("denominator of measurement unit is zero");
- _mag = readUnsigned(4);
- uint32_t pageHeight = readUnsigned(4); // height of tallest page in dvi units
- uint32_t pageWidth = readUnsigned(4); // width of widest page in dvi units
- uint16_t stackDepth = readUnsigned(2); // max. stack depth required
- uint16_t numPages = readUnsigned(2);
- if (numPages != (numberOfPages() & 0xffff))
- throw DVIException("page count in postamble doesn't match actual number of pages");
-
- // 1 dviunit * num/den == multiples of 0.0000001m
- // 1 dviunit * _dvi2bp: length of 1 dviunit in PS points * _mag/1000
- _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0;
- dviPost(stackDepth, numPages, pageWidth*_dvi2bp, pageHeight*_dvi2bp, _mag, numer, denom, prevBopOffset);
-}
-
-
-/** Reads and executes DVI post_post command.
- * Format: post_post q[4] i[1] 223[>=4] */
-void DVIReader::cmdPostPost (int) {
- uint32_t postOffset = readUnsigned(4); // pointer to begin of postamble
- uint8_t id = readUnsigned(1);
- setDVIVersion(DVIVersion(id)); // identification byte
- while (readUnsigned(1) == DVI_FILL); // skip fill bytes (223), eof bit should be set now
- dviPostPost(DVIVersion(id), postOffset);
-}
-
-
-/** Reads and executes Begin-Of-Page command.
- * Format: bop c0[+4] ... c9[+4] p[+4] */
-void DVIReader::cmdBop (int) {
- vector<int32_t> c(10);
- for (int i=0; i < 10; i++)
- c[i] = readSigned(4);
- int32_t prevBopOffset = readSigned(4); // pointer to peceeding bop (-1 in case of first page)
- _dviState.reset(); // set all DVI registers to 0
- while (!_stateStack.empty())
- _stateStack.pop();
- _currFontNum = 0;
- _inPage = true;
- dviBop(c, prevBopOffset);
-}
-
-
-/** Reads and executes End-Of-Page command. */
-void DVIReader::cmdEop (int) {
- if (!_stateStack.empty())
- throw DVIException("stack not empty at end of page");
- _inPage = false;
- dviEop();
-}
-
-
-/** Reads and executes push command. */
-void DVIReader::cmdPush (int) {
- _stateStack.push(_dviState);
- dviPush();
-}
-
-
-/** Reads and executes pop command (restores pushed position information). */
-void DVIReader::cmdPop (int) {
- if (_stateStack.empty())
- throw DVIException("stack empty at pop command");
- _dviState = _stateStack.top();
- _stateStack.pop();
- dviPop();
-}
-
-
-/** Helper function that handles charaters from virtual fonts (VF).
- * It is called by the cmdSetChar and cmdPutChar methods.
- * @param[in] font current font (corresponding to _currFontNum)
- * @param[in] c character to typeset */
-void DVIReader::putVFChar (Font *font, uint32_t c) {
- if (auto vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font?
- FontManager &fm = FontManager::instance();
- const vector<uint8_t> *dvi = vf->getDVI(c); // try to get DVI snippet that represents character c
- Font *firstFont = fm.vfFirstFont(vf);
- if (!dvi && (!firstFont || !dynamic_cast<const JFM*>(firstFont->getMetrics())))
- return;
- fm.enterVF(vf); // enter VF font number context
- int savedFontNum = _currFontNum; // save current font number
- setFont(fm.vfFirstFontNum(vf), SetFontMode::VF_ENTER);
- if (!dvi) // no definition present for current (Japanese) char?
- dviPutChar(c, firstFont); // fallback for JFM-based virtual fonts
- else {
- // DVI units in virtual fonts are multiples of 1^(-20) times the scaled size of the VF
- double savedScale = _dvi2bp;
- _dvi2bp = vf->scaledSize()/(1 << 20);
- DVIState savedState = _dviState; // save current cursor position
- _dviState.x = _dviState.y = _dviState.w = _dviState.z = 0;
- VectorInputStream<uint8_t> vis(*dvi);
- istream &is = replaceStream(vis);
- try {
- executeAll(); // execute DVI fragment
- }
- catch (const DVIException &e) {
- // Message::estream(true) << "invalid dvi in vf: " << e.getMessage() << endl; // @@
- }
- replaceStream(is); // restore previous input stream
- _dviState = savedState; // restore previous cursor position
- _dvi2bp = savedScale; // restore previous scale factor
- }
- fm.leaveVF(); // restore previous font number context
- setFont(savedFontNum, SetFontMode::VF_LEAVE); // restore previous font number
- }
-}
-
-
-/** Reads and executes set_char_x command. Puts a character at the current
- * position and advances the cursor.
- * @param[in] c character to set
- * @throw DVIException if method is called ouside a bop/eop pair */
-void DVIReader::cmdSetChar0 (int c) {
- if (!_inPage)
- throw DVIException("setchar outside of page");
- Font *font = FontManager::instance().getFont(_currFontNum);
- dviSetChar0(c, font); // template method that may trigger further actions
- putVFChar(font, c); // further character processing if current font is a virtual font
- moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0, MoveMode::SETCHAR);
-}
-
-
-/** Reads and executes setx command. Puts a character at the current
- * position and advances the cursor.
- * @param[in] len number of parameter bytes (possible values: 1-4)
- * @throw DVIException if method is called ouside a bop/eop pair */
-void DVIReader::cmdSetChar (int len) {
- if (!_inPage)
- throw DVIException("setchar outside of page");
- // According to the dvi specification all character codes are unsigned
- // except len == 4. At the moment all char codes are treated as unsigned...
- uint32_t c = readUnsigned(len); // if len == 4 c may be signed
- Font *font = FontManager::instance().getFont(_currFontNum);
- dviSetChar(c, font); // template method that may trigger further actions
- putVFChar(font, c); // further character processing if current font is a virtual font
- moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0, MoveMode::SETCHAR);
-}
-
-
-/** Reads and executes putx command. Puts a character at the current
- * position but doesn't change the cursor position.
- * @param[in] len number of parameter bytes (possible values: 1-4)
- * @throw DVIException if method is called ouside a bop/eop pair */
-void DVIReader::cmdPutChar (int len) {
- if (!_inPage)
- throw DVIException("putchar outside of page");
- // According to the dvi specification all character codes are unsigned
- // except len == 4. At the moment all char codes are treated as unsigned...
- int32_t c = readUnsigned(len);
- Font *font = FontManager::instance().getFont(_currFontNum);
- dviPutChar(c, font);
- putVFChar(font, c);
-}
-
-
-/** Reads and executes set_rule command. Puts a solid rectangle at the current
- * position and updates the cursor position.
- * Format: set_rule h[+4] w[+4]
- * @throw DVIException if method is called ouside a bop/eop pair */
-void DVIReader::cmdSetRule (int) {
- if (!_inPage)
- throw DVIException("set_rule outside of page");
- double height = _dvi2bp*readSigned(4);
- double width = _dvi2bp*readSigned(4);
- dviSetRule(height, width);
- moveRight(width, MoveMode::CHANGEPOS);
-}
-
-
-/** Reads and executes set_rule command. Puts a solid rectangle at the current
- * position but leaves the cursor position unchanged.
- * Format: put_rule h[+4] w[+4]
- * @throw DVIException if method is called ouside a bop/eop pair */
-void DVIReader::cmdPutRule (int) {
- if (!_inPage)
- throw DVIException("put_rule outside of page");
- double height = _dvi2bp*readSigned(4);
- double width = _dvi2bp*readSigned(4);
- dviPutRule(height, width);
-}
-
-
-void DVIReader::moveRight (double dx, MoveMode) {
- switch (_dviState.d) {
- case WritingMode::LR: _dviState.h += dx; break;
- case WritingMode::TB: _dviState.v += dx; break;
- case WritingMode::BT: _dviState.v -= dx; break;
- }
-}
-
-
-void DVIReader::moveDown (double dy, MoveMode) {
- switch (_dviState.d) {
- case WritingMode::LR: _dviState.v += dy; break;
- case WritingMode::TB: _dviState.h -= dy; break;
- case WritingMode::BT: _dviState.h += dy; break;
- }
-}
-
-
-void DVIReader::cmdRight (int len) {
- double dx = _dvi2bp*readSigned(len);
- moveRight(dx, MoveMode::CHANGEPOS);
- dviRight(dx);
-}
-
-
-void DVIReader::cmdDown (int len) {
- double dy = _dvi2bp*readSigned(len);
- moveDown(dy, MoveMode::CHANGEPOS);
- dviDown(dy);
-}
-
-
-void DVIReader::cmdNop (int) {dviNop();}
-void DVIReader::cmdX0 (int) {moveRight(_dviState.x, MoveMode::CHANGEPOS); dviX0();}
-void DVIReader::cmdY0 (int) {moveDown(_dviState.y, MoveMode::CHANGEPOS); dviY0();}
-void DVIReader::cmdW0 (int) {moveRight(_dviState.w, MoveMode::CHANGEPOS); dviW0();}
-void DVIReader::cmdZ0 (int) {moveDown(_dviState.z, MoveMode::CHANGEPOS); dviZ0();}
-
-
-void DVIReader::cmdX (int len) {
- double dx = _dvi2bp*readSigned(len);
- _dviState.x = dx;
- moveRight(dx, MoveMode::CHANGEPOS);
- dviX(dx);
-}
-
-
-void DVIReader::cmdY (int len) {
- double dy = _dvi2bp*readSigned(len);
- _dviState.y = dy;
- moveDown(dy, MoveMode::CHANGEPOS);
- dviY(dy);
-}
-
-
-void DVIReader::cmdW (int len) {
- double dx = _dvi2bp*readSigned(len);
- _dviState.w = dx;
- moveRight(dx, MoveMode::CHANGEPOS);
- dviW(dx);
-}
-
-
-void DVIReader::cmdZ (int len) {
- double dy = _dvi2bp*readSigned(len);
- _dviState.z = dy;
- moveDown(dy, MoveMode::CHANGEPOS);
- dviZ(dy);
-}
-
-
-/** Sets the text orientation (horizontal, vertical).
- * This command is only available in DVI version 3 (created by pTeX) */
-void DVIReader::cmdDir (int) {
- uint8_t wmode = readUnsigned(1);
- if (wmode == 4) // yoko mode (4) equals default LR mode (0)
- wmode = 0;
- if (wmode == 2 || wmode > 3)
- throw DVIException("invalid writing mode value " + std::to_string(wmode) + " (0, 1, 3, or 4 expected)");
- _dviState.d = (WritingMode)wmode;
- dviDir(_dviState.d);
-}
-
-
-void DVIReader::cmdXXX (int len) {
- if (!_inPage)
- throw DVIException("special outside of page");
- uint32_t numBytes = readUnsigned(len);
- string str = readString(numBytes);
- dviXXX(str);
-}
-
-
-/** Change the current font.
- * @param[in] fontnum local number of font to select
- * @param[in] mode info on command that triggered the font change
- * @throw DVIException if font number is undefined */
-void DVIReader::setFont (int fontnum, SetFontMode mode) {
- if (const Font *font = FontManager::instance().getFont(fontnum)) {
- _currFontNum = fontnum;
- dviFontNum(uint32_t(fontnum), mode, font);
- }
- else
- throw DVIException("undefined font number " + std::to_string(fontnum));
-}
-
-
-/** Selects a previously defined font by its number.
- * @param[in] fontnum font number
- * @throw DVIException if font number is undefined */
-void DVIReader::cmdFontNum0 (int fontnum) {
- setFont(fontnum, SetFontMode::SF_SHORT);
-}
-
-
-/** Selects a previously defined font.
- * @param[in] len size of font number variable (in bytes)
- * @throw DVIException if font number is undefined */
-void DVIReader::cmdFontNum (int len) {
- uint32_t fontnum = readUnsigned(len);
- setFont(fontnum, SetFontMode::SF_LONG);
-}
-
-
-/** Parses a sequence of font attributes given as key1=val1;key2=val2;...;keyn=valn */
-static map<string,string> parse_font_attribs (const string &str) {
- map<string,string> attribs;
- if (!str.empty()) {
- for (const string &attr : util::split(str, ";")) {
- vector<string> keyval = util::split(attr, "=");
- if (keyval.size() == 2)
- attribs[keyval[0]] = keyval[1];
- }
- }
- return attribs;
-}
-
-
-/** Helper function to handle a font definition.
- * @param[in] fontnum local font number
- * @param[in] name font name (or file path if enclosed in square brackets)
- * @param[in] cs checksum to be compared with TFM checksum
- * @param[in] dsize design size of font in PS point units
- * @param[in] ssize scaled size of font in PS point units */
-const Font* DVIReader::defineFont (uint32_t fontnum, const string &name, uint32_t cs, double dsize, double ssize) {
- FontManager &fm = FontManager::instance();
- Font *font = fm.getFont(fontnum);
- if (!font && !name.empty()) { // font not registered yet?
- if (name[0] == '[') { // LuaTeX native font reference?
- size_t last = name.rfind(']');
- if (last != string::npos) {
- string path = name.substr(1, last-1);
- FontStyle style;
- int fontIndex=0;
- if (name.size() > last && name[last+1] == ':') { // look for font attributes?
- auto attribs = parse_font_attribs(name.substr(last+2));
- auto it = attribs.begin();
- if ((it = attribs.find("index")) != attribs.end())
- fontIndex = stoi(it->second);
- if ((it = attribs.find("embolden")) != attribs.end())
- style.bold = stoi(it->second)/65536.0;
- if ((it = attribs.find("extend")) != attribs.end())
- style.extend = stoi(it->second)/65536.0;
- if ((it = attribs.find("slant")) != attribs.end())
- style.slant = stoi(it->second)/65536.0;
- }
- int id = fm.registerFont(fontnum, path, fontIndex, ssize, style, Color::BLACK);
- font = fm.getFontById(id);
- }
- }
- else { // TFM-based font specified by name
- int id = fm.registerFont(fontnum, name, cs, dsize, ssize);
- font = fm.getFontById(id);
- if (auto vf = dynamic_cast<VirtualFont*>(font)) {
- // read vf file, register its font and character definitions
- fm.enterVF(vf);
- ifstream ifs(vf->path(), ios::binary);
- VFReader vfReader(ifs);
- vfReader.replaceActions(this);
- vfReader.executeAll();
- fm.leaveVF();
- }
- }
- }
- return font;
-}
-
-
-/** Defines a new font.
- * @param[in] len size of font number variable (in bytes) */
-void DVIReader::cmdFontDef (int len) {
- uint32_t fontnum = readUnsigned(len); // font number
- uint32_t checksum = readUnsigned(4); // font checksum (to be compared with corresponding TFM checksum)
- uint32_t ssize = readUnsigned(4); // scaled size of font in DVI units
- uint32_t dsize = readUnsigned(4); // design size of font in DVI units
- uint32_t pathlen = readUnsigned(1); // length of font path
- uint32_t namelen = readUnsigned(1); // length of font name
- string path = readString(pathlen); // path to font file
- string fontname = readString(namelen);
- const Font *font = defineFont(fontnum, fontname, checksum, dsize*_dvi2bp, ssize*_dvi2bp);
- dviFontDef(fontnum, checksum, font);
-}
-
-
-/** This template method is called by the VFReader after reading a font definition from a VF file.
- * @param[in] fontnum local font number
- * @param[in] path path to font file
- * @param[in] name font name
- * @param[in] checksum checksum to be compared with TFM checksum
- * @param[in] dsize design size in PS point units
- * @param[in] ssize scaled size in PS point units */
-void DVIReader::defineVFFont (uint32_t fontnum, const string &path, const string &name, uint32_t checksum, double dsize, double ssize) {
- if (const VirtualFont *vf = FontManager::instance().getVF())
- defineFont(fontnum, name, checksum, dsize, ssize * vf->scaleFactor());
-}
-
-
-/** This template method is called by the VFReader after reading a character definition from a VF file.
- * @param[in] c character number
- * @param[in] dvi DVI fragment describing the character */
-void DVIReader::defineVFChar (uint32_t c, vector<uint8_t> &&dvi) {
- FontManager::instance().assignVFChar(c, std::move(dvi));
-}
-
-
-/** XDV extension: includes image or pdf file.
- * parameters: box[1] matrix[4][6] p[2] len[2] path[l] */
-void DVIReader::cmdXPic (int) {
- uint8_t box = readUnsigned(1); // box
- vector<int32_t> matrix(6);
- for (int i=0; i < 6; i++) // matrix
- matrix[i] = readSigned(4);
- int16_t page = readSigned(2); // page number
- uint16_t len = readUnsigned(2);
- string path = readString(len); // path to image/pdf file
- dviXPic(box, matrix, page, path);
-}
-
-
-/** XDV extension: defines a native font */
-void DVIReader::cmdXFontDef (int) {
- int32_t fontnum = readSigned(4);
- double ptsize = _dvi2bp*readUnsigned(4);
- uint16_t flags = readUnsigned(2);
- uint8_t psname_len = readUnsigned(1);
- uint8_t fmname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of family name
- uint8_t stname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of style name
- string fontname = readString(psname_len);
- uint32_t fontIndex=0;
- if (getDVIVersion() == DVI_XDV5)
- seek(fmname_len+stname_len, ios::cur);
- else
- fontIndex = readUnsigned(4);
- FontStyle style;
- Color color;
- if (flags & 0x0100) { // vertical?
- }
- if (flags & 0x0200) { // colored?
- // The font color must not interfere with color specials. If the font color is not black,
- // all color specials should be ignored, i.e. glyphs of a non-black fonts have a fixed color
- // that can't be changed by color specials.
- uint32_t rgba = readUnsigned(4);
- color.setRGB(uint8_t(rgba >> 24), uint8_t((rgba >> 16) & 0xff), uint8_t((rgba >> 8) & 0xff));
- }
- if (flags & 0x1000) // extend?
- style.extend = _dvi2bp*readSigned(4);
- if (flags & 0x2000) // slant?
- style.slant = _dvi2bp*readSigned(4);
- if (flags & 0x4000) // embolden?
- style.bold = _dvi2bp*readSigned(4);
- if ((flags & 0x0800) && (getDVIVersion() == DVI_XDV5)) { // variations?
- uint16_t num_variations = readSigned(2);
- for (int i=0; i < num_variations; i++)
- readUnsigned(4);
- }
- const Font *font = FontManager::instance().getFont(fontnum);
- if (!font) {
- FontManager::instance().registerFont(fontnum, fontname, fontIndex, ptsize, style, color);
- font = FontManager::instance().getFont(fontnum);
- }
- dviXFontDef(fontnum, dynamic_cast<const NativeFont*>(font));
-}
-
-
-/** XDV extension: prints an array of characters where each character
- * can take independent x and y coordinates.
- * parameters: w[4] n[2] (dx,dy)[(4+4)n] glyphs[2n] */
-void DVIReader::cmdXGlyphArray (int) {
- vector<double> dx, dy;
- vector<uint16_t> glyphs;
- double width = putGlyphArray(false, dx, dy, glyphs);
- if (Font *font = FontManager::instance().getFont(_currFontNum))
- dviXGlyphArray(dx, dy, glyphs, *font);
- else
- throw DVIException("missing setfont prior to xglypharray");
- moveRight(width, MoveMode::SETCHAR);
-}
-
-
-/** XDV extension: prints an array/string of characters where each character
- * can take independent x coordinates whereas all share a single y coordinate.
- * parameters: w[4] n[2] dx[4n] dy[4] glyphs[2n] */
-void DVIReader::cmdXGlyphString (int) {
- vector<double> dx, dy;
- vector<uint16_t> glyphs;
- double width = putGlyphArray(true, dx, dy, glyphs);
- if (Font *font = FontManager::instance().getFont(_currFontNum))
- dviXGlyphString(dx, glyphs, *font);
- else
- throw DVIException("missing setfont prior to xglyphstring");
- moveRight(width, MoveMode::SETCHAR);
-}
-
-
-/** XDV extension: Same as cmdXGlyphArray plus a leading array of UTF-16 characters
- * that specify the "actual text" represented by the glyphs to be printed. It usually
- * contains the text with special characters (like ligatures) expanded so that it
- * can be used for text search, plain text copy & paste etc. This XDV command was
- * introduced with XeTeX 0.99995 and can be triggered by <tt>\\XeTeXgenerateactualtext1</tt>.
- * parameters: l[2] chars[2l] w[4] n[2] (dx,dy)[8n] glyphs[2n] */
-void DVIReader::cmdXTextAndGlyphs (int) {
- uint16_t l = readUnsigned(2); // number of chars
- vector<uint16_t> chars(l);
- for (int i=0; i < l; i++)
- chars[i] = readUnsigned(2);
- vector<double> x, y;
- vector<uint16_t> glyphs;
- double width = putGlyphArray(false, x, y, glyphs);
- if (Font *font = FontManager::instance().getFont(_currFontNum))
- dviXTextAndGlyphs(x, y, chars, glyphs, *font);
- else
- throw DVIException("missing setfont prior to xtextandglyphs");
- moveRight(width, MoveMode::SETCHAR);
-}
-
-
-/** Implements the common functionality of cmdXGlyphArray, cmdXGlyphString, and cmdXTextAndGlyphs.
- * @param[in] xonly indicates if the characters share a single y coordinate (xonly==true)
- * @param[out] dx relative horizontal positions of each glyph
- * @param[out] dy relative vertical positions of each glyph
- * @param[out] glyphs FreeType indices of the glyphs to typeset
- * @return total width of the glyph array */
-double DVIReader::putGlyphArray (bool xonly, vector<double> &dx, vector<double> &dy, vector<uint16_t> &glyphs) {
- double strwidth = _dvi2bp*readSigned(4);
- uint16_t num_glyphs = readUnsigned(2);
- dx.resize(num_glyphs);
- dy.resize(num_glyphs);
- glyphs.resize(num_glyphs);
- for (int i=0; i < num_glyphs; i++) {
- dx[i] = readSigned(4)*_dvi2bp;
- dy[i] = xonly ? 0 : readSigned(4)*_dvi2bp;
- }
- for (int i=0; i < num_glyphs; i++)
- glyphs[i] = readUnsigned(2);
- return strwidth;
-}