diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2016-07-04 22:07:54 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2016-07-04 22:07:54 +0000 |
commit | ab399d16f49b986d1de514b2fb8434872decf91d (patch) | |
tree | 6d3d0faca673d7aa1c0f48ca679ce7841a82e3df /Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp | |
parent | dd2749b37f7b6a9976869e29a028eeab80d686df (diff) |
dvisvgm 1.16
git-svn-id: svn://tug.org/texlive/trunk@41628 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp | 518 |
1 files changed, 253 insertions, 265 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp index deacce1871c..3c6c2c1d284 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp @@ -28,26 +28,17 @@ #include "DVIReader.h" #include "Font.h" #include "FontManager.h" -#include "SignalHandler.h" #include "VectorStream.h" - using namespace std; -bool DVIReader::COMPUTE_PROGRESS = false; - - -DVIReader::DVIReader (istream &is, DVIActions *a) : BasicDVIReader(is), _actions(a) +DVIReader::DVIReader (istream &is) : BasicDVIReader(is) { _inPage = false; - _pageHeight = _pageWidth = 0; _dvi2bp = 0.0; - _tx = _ty = 0; // no cursor translation - _prevYPos = numeric_limits<double>::min(); _inPostamble = false; _currFontNum = 0; _currPageNum = 0; - _pagePos = 0; _mag = 1; executePreamble(); collectBopOffsets(); @@ -55,39 +46,9 @@ DVIReader::DVIReader (istream &is, DVIActions *a) : BasicDVIReader(is), _actions } -DVIActions* DVIReader::replaceActions (DVIActions *a) { - DVIActions *prev_actions = _actions; - _actions = a; - return prev_actions; -} - - -/** Reads a single DVI command from the current position of the input stream and calls the - * corresponding cmdFOO method. - * @return opcode of the command executed */ int DVIReader::executeCommand () { - SignalHandler::instance().check(); - CommandHandler handler; - int param; // parameter of handler - const streampos cmdpos = tell(); - int opcode = evalCommand(handler, param); - (this->*handler)(param); - if (_dviState.v+_ty != _prevYPos) { - _tx = _ty = 0; - _prevYPos = _dviState.v; - } - if (COMPUTE_PROGRESS && _inPage && _actions) { - size_t pagelen = numberOfPageBytes(_currPageNum-1); - // ensure progress() is called at 0% - if (opcode == 139) // bop? - _actions->progress(0, pagelen); - // ensure progress() is called at 100% - if (peek() == 140) // eop reached? - _pagePos = pagelen; - else - _pagePos += tell()-cmdpos; - _actions->progress(_pagePos, pagelen); - } + _prevDviState = _currDviState; + int opcode = BasicDVIReader::executeCommand(); return opcode; } @@ -181,65 +142,48 @@ void DVIReader::collectBopOffsets () { reverse(_bopOffsets.begin(), _bopOffsets.end()); } - -/** Returns the current x coordinate in PS point units. - * This is the horizontal position where the next output would be placed. */ -double DVIReader::getXPos () const { - return _dviState.h+_tx; -} - - -/** Returns the current y coordinate in PS point units. - * This is the vertical position where the next output would be placed. */ -double DVIReader::getYPos () const { - return _dviState.v+_ty; -} - - ///////////////////////////////////// /** Reads and executes DVI preamble command. * Format: pre ver[1] num[4] den[4] mag[4] cmtlen[1] cmt[cmtlen] */ void DVIReader::cmdPre (int) { - setDVIFormat((DVIFormat)readUnsigned(1)); // identification number - UInt32 num = readUnsigned(4); // numerator units of measurement - UInt32 den = readUnsigned(4); // denominator units of measurement - if (den == 0) + UInt8 id = readUnsigned(1); + setDVIVersion(DVIVersion(id)); // identification number + UInt32 numer = readUnsigned(4); // numerator units of measurement + UInt32 denom = readUnsigned(4); // denominator units of measurement + if (denom == 0) throw DVIException("denominator of measurement unit is zero"); _mag = readUnsigned(4); // magnification - UInt32 k = readUnsigned(1); // length of following comment - string cmt = readString(k); // comment + UInt32 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 = num/254000.0*72.0/den*_mag/1000.0; - if (_actions) - _actions->preamble(cmt); + _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) { - readUnsigned(4); // skip pointer to previous bop - UInt32 num = readUnsigned(4); - UInt32 den = readUnsigned(4); - if (den == 0) + UInt32 prevBopOffset = readUnsigned(4); + UInt32 numer = readUnsigned(4); + UInt32 denom = readUnsigned(4); + if (denom == 0) throw DVIException("denominator of measurement unit is zero"); _mag = readUnsigned(4); - _pageHeight = readUnsigned(4); // height of tallest page in dvi units - _pageWidth = readUnsigned(4); // width of widest page in dvi units - readUnsigned(2); // skip max. stack depth - if (readUnsigned(2) != numberOfPages()) - throw DVIException("page count entry doesn't match actual number of pages"); + UInt32 pageHeight = readUnsigned(4); // height of tallest page in dvi units + UInt32 pageWidth = readUnsigned(4); // width of widest page in dvi units + UInt16 stackDepth = readUnsigned(2); // max. stack depth required + UInt16 numPages = readUnsigned(2); + if (numPages != numberOfPages()) + 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 = num/254000.0*72.0/den*_mag/1000.0; - _pageHeight *= _dvi2bp; // to pt units - _pageWidth *= _dvi2bp; + _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0; _inPostamble = true; - if (_actions) - _actions->postamble(); + dviPost(stackDepth, numPages, pageWidth*_dvi2bp, pageHeight*_dvi2bp, _mag, numer, denom, prevBopOffset); } @@ -247,28 +191,27 @@ void DVIReader::cmdPost (int) { * Format: post_post q[4] i[1] 223[>=4] */ void DVIReader::cmdPostPost (int) { _inPostamble = false; - readUnsigned(4); // pointer to begin of postamble - setDVIFormat((DVIFormat)readUnsigned(1)); // identification byte + UInt32 postOffset = readUnsigned(4); // pointer to begin of postamble + UInt8 id = readUnsigned(1); + setDVIVersion(DVIVersion(id)); // identification byte while (readUnsigned(1) == 223); // 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) { - Int32 c[10]; + vector<Int32> c(10); for (int i=0; i < 10; i++) c[i] = readSigned(4); - readSigned(4); // pointer to peceeding bop (-1 in case of first page) - _dviState.reset(); // set all DVI registers to 0 + Int32 prevBopOffset = readSigned(4); // pointer to peceeding bop (-1 in case of first page) + _currDviState.reset(); // set all DVI registers to 0 while (!_stateStack.empty()) _stateStack.pop(); _currFontNum = 0; _inPage = true; - _pagePos = 0; - beginPage(_currPageNum, c); - if (_actions) - _actions->beginPage(_currPageNum, c); + dviBop(c, prevBopOffset); } @@ -277,15 +220,14 @@ void DVIReader::cmdEop (int) { if (!_stateStack.empty()) throw DVIException("stack not empty at end of page"); _inPage = false; - endPage(_currPageNum); - if (_actions) - _actions->endPage(_currPageNum); + dviEop(); } /** Reads and executes push command. */ void DVIReader::cmdPush (int) { - _stateStack.push(_dviState); + _stateStack.push(_currDviState); + dviPush(); } @@ -293,72 +235,41 @@ void DVIReader::cmdPush (int) { void DVIReader::cmdPop (int) { if (_stateStack.empty()) throw DVIException("stack empty at pop command"); - else { - DVIState prevState = _dviState; - _dviState = _stateStack.top(); - _stateStack.pop(); - if (_actions) { - if (prevState.h != _dviState.h) - _actions->moveToX(_dviState.h + _tx); - if (prevState.v != _dviState.v) - _actions->moveToY(_dviState.v + _ty); - if (prevState.d != _dviState.d) - _actions->setTextOrientation(_dviState.d != WMODE_LR); - } - } -} - - -/** Helper function that actually sets/puts a charater. It is called by the - * cmdSetChar and cmdPutChar methods. - * @param[in] c character to typeset - * @param[in] moveCursor if true, register h is increased by the character width - * @throw DVIException if method is called ouside a bop/eop pair */ -void DVIReader::putChar (UInt32 c, bool moveCursor) { - if (!_inPage) - throw DVIException("set_char/put_char outside of page"); - - FontManager &fm = FontManager::instance(); - Font *font = fm.getFont(_currFontNum); - if (!font) - throw DVIException("no font selected"); - - if (VirtualFont *vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font? - vector<UInt8> *dvi = const_cast<vector<UInt8>*>(vf->getDVI(c)); // get DVI snippet that describes character c - if (dvi) { - DVIState pos = _dviState; // save current cursor position - _dviState.x = _dviState.y = _dviState.w = _dviState.z = 0; - int save_fontnum = _currFontNum; // save current font number - fm.enterVF(vf); // new font number context - cmdFontNum0(fm.vfFirstFontNum(vf)); - double save_scale = _dvi2bp; + _currDviState = _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 c) { + if (VirtualFont *vf = dynamic_cast<VirtualFont*>(font)) { // is current font a virtual font? + if (const vector<UInt8> *dvi = vf->getDVI(c)) { // try to get DVI snippet that represents character c + FontManager &fm = FontManager::instance(); + DVIState pos = _currDviState; // save current cursor position + _currDviState.x = _currDviState.y = _currDviState.w = _currDviState.z = 0; + int savedFontNum = _currFontNum; // save current font number + fm.enterVF(vf); // enter VF font number context + setFont(fm.vfFirstFontNum(vf), VF_ENTER); + double savedScale = _dvi2bp; // DVI units in virtual fonts are multiples of 1^(-20) times the scaled size of the VF _dvi2bp = vf->scaledSize()/(1 << 20); - VectorInputStream<UInt8> vis(*dvi); istream &is = replaceStream(vis); try { - executeAll(); // execute DVI fragment + executeAll(); // execute DVI fragment } catch (const DVIException &e) { - // Message::estream(true) << "invalid dvi in vf: " << e.getMessage() << endl; // @@ + // Message::estream(true) << "invalid dvi in vf: " << e.getMessage() << endl; // @@ } - replaceStream(is); // restore previous input stream - _dvi2bp = save_scale; // restore previous scale factor - fm.leaveVF(); // restore previous font number context - cmdFontNum0(save_fontnum); // restore previous font number - _dviState = pos; // restore previous cursor position - } - } - else if (_actions) - _actions->setChar(_dviState.h+_tx, _dviState.v+_ty, c, _dviState.d != WMODE_LR, font); - - if (moveCursor) { - double dist = font->charWidth(c) * font->scaleFactor() * _mag/1000.0; - switch (_dviState.d) { - case WMODE_LR: _dviState.h += dist; break; - case WMODE_TB: _dviState.v += dist; break; - case WMODE_BT: _dviState.v -= dist; break; + replaceStream(is); // restore previous input stream + _dvi2bp = savedScale; // restore previous scale factor + fm.leaveVF(); // restore previous font number context + setFont(savedFontNum, VF_LEAVE); // restore previous font number + _currDviState = pos; // restore previous cursor position } } } @@ -369,7 +280,12 @@ void DVIReader::putChar (UInt32 c, bool moveCursor) { * @param[in] c character to set * @throw DVIException if method is called ouside a bop/eop pair */ void DVIReader::cmdSetChar0 (int c) { - putChar(c, true); + if (!_inPage) + throw DVIException("setchar outside of page"); + Font *font = FontManager::instance().getFont(_currFontNum); + moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0); + dviSetChar0(c, font); + putVFChar(font, c); } @@ -378,10 +294,15 @@ void DVIReader::cmdSetChar0 (int c) { * @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 c = readUnsigned(len); // if len == 4 c may be signed - putChar(c, true); + Font *font = FontManager::instance().getFont(_currFontNum); + moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0); + dviSetChar(c, font); + putVFChar(font, c); } @@ -390,10 +311,14 @@ void DVIReader::cmdSetChar (int len) { * @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 c = readUnsigned(len); - putChar(c, false); + Font *font = FontManager::instance().getFont(_currFontNum); + dviPutChar(c, font); + putVFChar(font, c); } @@ -406,9 +331,8 @@ void DVIReader::cmdSetRule (int) { throw DVIException("set_rule outside of page"); double height = _dvi2bp*readSigned(4); double width = _dvi2bp*readSigned(4); - if (_actions && height > 0 && width > 0) - _actions->setRule(_dviState.h+_tx, _dviState.v+_ty, height, width); moveRight(width); + dviSetRule(height, width); } @@ -421,68 +345,94 @@ void DVIReader::cmdPutRule (int) { throw DVIException("put_rule outside of page"); double height = _dvi2bp*readSigned(4); double width = _dvi2bp*readSigned(4); - if (_actions && height > 0 && width > 0) - _actions->setRule(_dviState.h+_tx, _dviState.v+_ty, height, width); + dviPutRule(height, width); } void DVIReader::moveRight (double dx) { - switch (_dviState.d) { - case WMODE_LR: _dviState.h += dx; break; - case WMODE_TB: _dviState.v += dx; break; - case WMODE_BT: _dviState.v -= dx; break; - } - if (_actions) { - if (_dviState.d == WMODE_LR) - _actions->moveToX(_dviState.h+_tx); - else - _actions->moveToY(_dviState.v+_ty); + switch (_currDviState.d) { + case WMODE_LR: _currDviState.h += dx; break; + case WMODE_TB: _currDviState.v += dx; break; + case WMODE_BT: _currDviState.v -= dx; break; } } void DVIReader::moveDown (double dy) { - switch (_dviState.d) { - case WMODE_LR: _dviState.v += dy; break; - case WMODE_TB: _dviState.h -= dy; break; - case WMODE_BT: _dviState.h += dy; break; - } - if (_actions) { - if (_dviState.d == WMODE_LR) - _actions->moveToY(_dviState.v+_ty); - else - _actions->moveToX(_dviState.h+_tx); + switch (_currDviState.d) { + case WMODE_LR: _currDviState.v += dy; break; + case WMODE_TB: _currDviState.h -= dy; break; + case WMODE_BT: _currDviState.h += dy; break; } } -void DVIReader::cmdRight (int len) {moveRight(_dvi2bp*readSigned(len));} -void DVIReader::cmdDown (int len) {moveDown(_dvi2bp*readSigned(len));} -void DVIReader::cmdX0 (int) {moveRight(_dviState.x);} -void DVIReader::cmdY0 (int) {moveDown(_dviState.y);} -void DVIReader::cmdW0 (int) {moveRight(_dviState.w);} -void DVIReader::cmdZ0 (int) {moveDown(_dviState.z);} -void DVIReader::cmdX (int len) {_dviState.x = _dvi2bp*readSigned(len); cmdX0(0);} -void DVIReader::cmdY (int len) {_dviState.y = _dvi2bp*readSigned(len); cmdY0(0);} -void DVIReader::cmdW (int len) {_dviState.w = _dvi2bp*readSigned(len); cmdW0(0);} -void DVIReader::cmdZ (int len) {_dviState.z = _dvi2bp*readSigned(len); cmdZ0(0);} -void DVIReader::cmdNop (int) {} +void DVIReader::cmdRight (int len) { + Int32 dx = _dvi2bp*readSigned(len); + moveRight(dx); + dviRight(dx); +} + + +void DVIReader::cmdDown (int len) { + Int32 dy = _dvi2bp*readSigned(len); + moveDown(dy); + dviDown(dy); +} + + +void DVIReader::cmdNop (int) {} +void DVIReader::cmdX0 (int) {moveRight(_currDviState.x); dviX0();} +void DVIReader::cmdY0 (int) {moveDown(_currDviState.y); dviY0();} +void DVIReader::cmdW0 (int) {moveRight(_currDviState.w); dviW0();} +void DVIReader::cmdZ0 (int) {moveDown(_currDviState.z); dviZ0();} + + +void DVIReader::cmdX (int len) { + Int32 dx = _dvi2bp*readSigned(len); + _currDviState.x = dx; + moveRight(dx); + dviX(dx); +} + + +void DVIReader::cmdY (int len) { + Int32 dy = _dvi2bp*readSigned(len); + _currDviState.y = dy; + moveDown(dy); + dviY(dy); +} + + +void DVIReader::cmdW (int len) { + Int32 dx = _dvi2bp*readSigned(len); + _currDviState.w = dx; + moveRight(dx); + dviW(dx); +} + + +void DVIReader::cmdZ (int len) { + Int32 dy = _dvi2bp*readSigned(len); + _currDviState.z = dy; + moveDown(dy); + dviZ(dy); +} /** Sets the text orientation (horizontal, vertical). - * This command is only available in DVI files of format 3 (created by pTeX) */ + * This command is only available in DVI version 3 (created by pTeX) */ void DVIReader::cmdDir (int) { UInt8 wmode = readUnsigned(1); if (wmode == 4) // yoko mode (4) equals default LR mode (0) wmode = 0; if (wmode == 2 || wmode > 3) { ostringstream oss; - oss << "invalid writing mode value " << wmode << " (0, 1, or 3 expected)"; + oss << "invalid writing mode value " << wmode << " (0, 1, 3, or 4 expected)"; throw DVIException(oss.str()); } - _dviState.d = (WritingMode)wmode; - if (_actions) - _actions->setTextOrientation(_dviState.d != WMODE_LR); + _currDviState.d = (WritingMode)wmode; + dviDir(_currDviState.d); } @@ -490,35 +440,42 @@ void DVIReader::cmdXXX (int len) { if (!_inPage) throw DVIException("special outside of page"); UInt32 numBytes = readUnsigned(len); - string s = readString(numBytes); - if (_actions) - _actions->special(s, _dvi2bp); + string str = readString(numBytes); + dviXXX(str); } -/** Selects a previously defined font by its number. - * @param[in] num font number - * @throw DVIException if font number is undefined */ -void DVIReader::cmdFontNum0 (int num) { - if (Font *font = FontManager::instance().getFont(num)) { - _currFontNum = num; - if (_actions && !dynamic_cast<VirtualFont*>(font)) - _actions->setFont(FontManager::instance().fontID(num), *font); // all fonts get a recomputed ID +/** 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(fontnum), mode, font); } else { ostringstream oss; - oss << "undefined font number " << num; + oss << "undefined font number " << fontnum; throw DVIException(oss.str()); } } +/** 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, SF_SHORT); +} + + /** Selects a previously defined font. - * @param[in] len size of font number variable (in bytes) - * @throw DVIException if font number is undefined */ + * @param[in] len size of font number variable (in bytes) + * @throw DVIException if font number is undefined */ void DVIReader::cmdFontNum (int len) { - UInt32 num = readUnsigned(len); - cmdFontNum0(num); + UInt32 fontnum = readUnsigned(len); + setFont(fontnum, SF_LONG); } @@ -528,29 +485,28 @@ void DVIReader::cmdFontNum (int len) { * @param[in] cs checksum to be compared with TFM checksum * @param[in] ds design size in PS point units * @param[in] ss scaled size in PS point units */ -void DVIReader::defineFont (UInt32 fontnum, const string &name, UInt32 cs, double ds, double ss) { - if (!_inPostamble) // only process font definitions collected in the postamble; skip all others - return; - +const Font* DVIReader::defineFont (UInt32 fontnum, const string &name, UInt32 cs, double ds, double ss) { FontManager &fm = FontManager::instance(); - int id = fm.registerFont(fontnum, name, cs, ds, ss); - Font *font = fm.getFontById(id); - if (VirtualFont *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(); + Font *font = fm.getFont(fontnum); + if (!font) { + int id = fm.registerFont(fontnum, name, cs, ds, ss); + font = fm.getFontById(id); + if (VirtualFont *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(); + } } - if (_actions) - _actions->defineFont(id, font); + return font; } /** Defines a new font. - * @param[in] len size of font number variable (in bytes) */ + * @param[in] len size of font number variable (in bytes) */ void DVIReader::cmdFontDef (int len) { UInt32 fontnum = readUnsigned(len); // font number UInt32 checksum = readUnsigned(4); // font checksum (to be compared with corresponding TFM checksum) @@ -558,10 +514,10 @@ void DVIReader::cmdFontDef (int len) { UInt32 dsize = readUnsigned(4); // design size of font in DVI units UInt32 pathlen = readUnsigned(1); // length of font path UInt32 namelen = readUnsigned(1); // length of font name - readString(pathlen); // skip font path + string path = readString(pathlen); // path to font file string fontname = readString(namelen); - - defineFont(fontnum, fontname, checksum, dsize*_dvi2bp, ssize*_dvi2bp); + const Font *font = defineFont(fontnum, fontname, checksum, dsize*_dvi2bp, ssize*_dvi2bp); + dviFontDef(fontnum, checksum, font); } @@ -573,7 +529,7 @@ void DVIReader::cmdFontDef (int len) { * @param[in] dsize design size in PS point units * @param[in] ssize scaled size in PS point units */ void DVIReader::defineVFFont (UInt32 fontnum, string path, string name, UInt32 checksum, double dsize, double ssize) { - if (VirtualFont *vf = FontManager::instance().getVF()) + if (const VirtualFont *vf = FontManager::instance().getVF()) defineFont(fontnum, name, checksum, dsize, ssize * vf->scaleFactor()); } @@ -589,13 +545,14 @@ void DVIReader::defineVFChar (UInt32 c, vector<UInt8> *dvi) { /** XDV extension: includes image or pdf file. * parameters: box[1] matrix[4][6] p[2] len[2] path[l] */ void DVIReader::cmdXPic (int) { - // just skip the parameters - readUnsigned(1); // box - for (int i=0; i < 6; i++) // matrix - readSigned(4); - readSigned(2); // page number + UInt8 box = readUnsigned(1); // box + vector<Int32> matrix(6); + for (int i=0; i < 6; i++) // matrix + matrix[i] = readSigned(4); + Int16 page = readSigned(2); // page number UInt16 len = readUnsigned(2); - readString(len); // path to image/pdf file + string path = readString(len); // path to image/pdf file + dviXPic(box, matrix, page, path); } @@ -605,11 +562,11 @@ void DVIReader::cmdXFontDef (int) { double ptsize = _dvi2bp*readUnsigned(4); UInt16 flags = readUnsigned(2); UInt8 psname_len = readUnsigned(1); - UInt8 fmname_len = getDVIFormat() == DVI_XDVOLD ? readUnsigned(1) : 0; - UInt8 stname_len = getDVIFormat() == DVI_XDVOLD ? readUnsigned(1) : 0; + UInt8 fmname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of family name + UInt8 stname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of style name string fontname = readString(psname_len); UInt32 fontIndex=0; - if (getDVIFormat() == DVI_XDVOLD) + if (getDVIVersion() == DVI_XDV5) seek(fmname_len+stname_len, ios::cur); else fontIndex = readUnsigned(4); @@ -630,54 +587,85 @@ void DVIReader::cmdXFontDef (int) { style.slant = _dvi2bp*readSigned(4); if (flags & 0x4000) // embolden? style.bold = _dvi2bp*readSigned(4); - if ((flags & 0x0800) && (getDVIFormat() == DVI_XDVOLD)) { // variations? + if ((flags & 0x0800) && (getDVIVersion() == DVI_XDV5)) { // variations? UInt16 num_variations = readSigned(2); for (int i=0; i < num_variations; i++) readUnsigned(4); } - if (_inPage) + 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] x[4][n] y[4][n] c[2][n] */ + * parameters: w[4] n[2] (dx,dy)[(4+4)n] glyphs[2n] */ void DVIReader::cmdXGlyphArray (int) { - putGlyphArray(false); + vector<double> dx, dy; + vector<UInt16> glyphs; + 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"); } /** 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] x[4][n] y[4] c[2][n] */ + * parameters: w[4] n[2] dx[4n] dy[4] glyphs[2n] */ void DVIReader::cmdXGlyphString (int) { - putGlyphArray(true); + vector<double> dx, dy; + vector<UInt16> glyphs; + putGlyphArray(true, dx, dy, glyphs); + if (Font *font = FontManager::instance().getFont(_currFontNum)) + dviXGlyphString(dx, glyphs, *font); + else + throw DVIException("missing setfont prior to xglyphstring"); +} + + +/** 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 l = readUnsigned(2); // number of chars + vector<UInt16> chars(l); + for (int i=0; i < l; i++) + chars[i] = readUnsigned(2); + vector<double> x, y; + vector<UInt16> glyphs; + 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"); } -/** Implements the common functionality of cmdXGlyphA and cmdXGlyphS. - * @param[in] xonly indicates if the characters share a single y coordinate (xonly==true) */ -void DVIReader::putGlyphArray (bool xonly) { +/** 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 */ +void DVIReader::putGlyphArray (bool xonly, vector<double> &dx, vector<double> &dy, vector<UInt16> &glyphs) { double strwidth = _dvi2bp*readSigned(4); UInt16 num_glyphs = readUnsigned(2); - vector<Int32> x(num_glyphs); - vector<Int32> y(num_glyphs); + dx.resize(num_glyphs); + dy.resize(num_glyphs); + glyphs.resize(num_glyphs); for (int i=0; i < num_glyphs; i++) { - x[i] = readSigned(4); - y[i] = xonly ? 0 : readSigned(4); - } - if (!_actions) - seek(2*num_glyphs, ios::cur); - else { - if (Font *font = FontManager::instance().getFont(_currFontNum)) { - for (int i=0; i < num_glyphs; i++) { - UInt16 glyph_index = readUnsigned(2); - double xx = _dviState.h + x[i]*_dvi2bp + _tx; - double yy = _dviState.v + y[i]*_dvi2bp + _ty; - _actions->setChar(xx, yy, glyph_index, false, font); - } - } + dx[i] = readSigned(4)*_dvi2bp; + dy[i] = xonly ? 0 : readSigned(4)*_dvi2bp; } + for (int i=0; i < num_glyphs; i++) + glyphs[i] = readUnsigned(2); moveRight(strwidth); } |