summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2016-07-04 22:07:54 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2016-07-04 22:07:54 +0000
commitab399d16f49b986d1de514b2fb8434872decf91d (patch)
tree6d3d0faca673d7aa1c0f48ca679ce7841a82e3df /Build/source/texk/dvisvgm/dvisvgm-src/src/DVIReader.cpp
parentdd2749b37f7b6a9976869e29a028eeab80d686df (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.cpp518
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);
}