1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
2 // dviRenderer_prescan.cpp
4 // Part of KDVI - A DVI previewer for the KDE desktop environment
6 // (C) 2003--2004 Stefan Kebekus
7 // Distributed under the GPL
11 #include "dviRenderer.h"
14 #include "kvs_debug.h"
15 #include "prebookmark.h"
20 #include <kmessagebox.h>
21 #include <kmimetype.h>
25 #include <QApplication>
29 #include <QPaintDevice>
30 #include <QProgressBar>
31 #include <QTextStream>
34 extern QPainter foreGroundPaint
;
35 extern void parse_special_argument(const QString
& strg
, const char* argument_name
, int* variable
);
38 //#define DEBUG_PRESCAN
41 void dviRenderer::prescan_embedPS(char *cp
, quint8
*beginningOfSpecialCommand
)
44 kDebug(kvs::dvi
) << "dviRenderer::prescan_embedPS( cp = " << cp
<< " ) ";
47 // Encapsulated Postscript File
48 if (strncasecmp(cp
, "PSfile=", 7) != 0)
51 QString
command(cp
+7);
53 QString include_command
= command
.simplified();
55 // The line is supposed to start with "..ile=", and then comes the
56 // filename. Figure out what the filename is and stow it away. Of
57 // course, this does not work if the filename contains spaces
58 // (already the simplified() above is wrong). If you have
59 // files like this, go away.
60 QString EPSfilename
= include_command
;
61 EPSfilename
.truncate(EPSfilename
.indexOf(' '));
63 // Strip enclosing quotation marks which are included by some LaTeX
64 // macro packages (but not by others). This probably means that
65 // graphic files are no longer found if the filename really does
66 // contain quotes, but we don't really care that much.
67 if ((EPSfilename
.at(0) == '\"') && (EPSfilename
.at(EPSfilename
.length()-1) == '\"'))
68 EPSfilename
= EPSfilename
.mid(1,EPSfilename
.length()-2);
70 // Now locate the Gfx file on the hard disk...
71 EPSfilename
= ghostscript_interface::locateEPSfile(EPSfilename
, baseURL
);
73 // If the file is neither a PostScript not a PDF file, we exit here.
74 // The graphic file is later read when the page is rendered.
75 KMimeType::Ptr
const mime_type
=
76 KMimeType::findByFileContent(EPSfilename
);
77 QString
const & mime_type_name
= mime_type
?mime_type
->name():"";
79 bool const is_ps_file
= (mime_type_name
== "application/postscript" ||
80 mime_type_name
== "image/x-eps");
81 bool const is_pdf_file
= (!is_ps_file
&&
82 mime_type_name
== "application/pdf");
83 if (!(is_ps_file
|| is_pdf_file
))
86 QString originalFName
= EPSfilename
;
88 embedPS_progress
->setLabelText(i18n("Embedding %1", EPSfilename
));
89 qApp
->processEvents();
91 // If the EPSfilename really points to a PDF file, convert that file now.
93 EPSfilename
= dviFile
->convertPDFtoPS(EPSfilename
);
95 if (!QFile::exists(EPSfilename
)) {
96 // Find the number of the page
97 quint32 currentOffset
= beginningOfSpecialCommand
- dviFile
->dvi_Data();
99 for(; page
< dviFile
->total_pages
; page
++)
100 if ((dviFile
->page_offset
[page
] <= currentOffset
) && (currentOffset
<= dviFile
->page_offset
[page
+1]))
103 errorMsg
+= i18n("Page %1: The PDF file <strong>%2</strong> could not be converted to PostScript.<br>", page
+1, originalFName
);
105 errorMsg
+= i18n("Page %1: The PostScript file <strong>%2</strong> could not be found.<br>", page
+1, originalFName
);
106 embedPS_progress
->progressBar()->setValue(embedPS_progress
->progressBar()->value()+1);
107 qApp
->processEvents();
111 // Now parse the arguments.
120 // just to avoid ambiguities; the filename could contain keywords
121 include_command
= include_command
.mid(include_command
.indexOf(' '));
123 parse_special_argument(include_command
, "llx=", &llx
);
124 parse_special_argument(include_command
, "lly=", &lly
);
125 parse_special_argument(include_command
, "urx=", &urx
);
126 parse_special_argument(include_command
, "ury=", &ury
);
127 parse_special_argument(include_command
, "rwi=", &rwi
);
128 parse_special_argument(include_command
, "rhi=", &rhi
);
129 parse_special_argument(include_command
, "angle=", &angle
);
131 int clip
=include_command
.indexOf(" clip"); // -1 if clip keyword is not present, >= 0 otherwise
133 // Generate the PostScript commands to be included
134 QString PS
= QString("ps: @beginspecial %1 @llx %2 @lly %3 @urx %4 @ury").arg(llx
).arg(lly
).arg(urx
).arg(ury
);
136 PS
.append( QString(" %1 @rwi").arg(rwi
) );
138 PS
.append( QString(" %1 @rhi").arg(rhi
) );
140 PS
.append( QString(" %1 @angle").arg(angle
) );
143 PS
.append( " @setspecial\n" );
145 QFile
file( EPSfilename
);
146 if ( file
.open( QIODevice::ReadOnly
) ) {
147 QTextStream
stream( &file
);
148 while ( !stream
.atEnd() ) {
149 PS
+= stream
.readLine().section( '%', 0, 0);
154 PS
.append( "@endspecial" );
155 PS
= PS
.simplified();
159 quint32 lengthOfOldSpecial
= command_pointer
- beginningOfSpecialCommand
;
160 quint32 lengthOfNewSpecial
= PS
.length()+5;
162 Q3MemArray
<quint8
> newDVI(dviFile
->size_of_file
+ lengthOfNewSpecial
-lengthOfOldSpecial
);
164 quint8
*commandPtrSav
= command_pointer
;
165 quint8
*endPtrSav
= end_pointer
;
166 end_pointer
= newDVI
.data() + dviFile
->size_of_file
+ lengthOfNewSpecial
-lengthOfOldSpecial
;
167 memcpy(newDVI
.data(), dviFile
->dvi_Data(), beginningOfSpecialCommand
-dviFile
->dvi_Data());
168 command_pointer
= newDVI
.data()+(beginningOfSpecialCommand
-dviFile
->dvi_Data());
169 command_pointer
[0] = XXX4
;
171 writeUINT32(PS
.length());
172 memcpy(newDVI
.data()+(beginningOfSpecialCommand
-dviFile
->dvi_Data())+5, PS
.toLatin1(), PS
.length() );
173 memcpy(newDVI
.data()+(beginningOfSpecialCommand
-dviFile
->dvi_Data())+lengthOfNewSpecial
, beginningOfSpecialCommand
+lengthOfOldSpecial
,
174 dviFile
->size_of_file
-(beginningOfSpecialCommand
-dviFile
->dvi_Data())-lengthOfOldSpecial
);
176 // Adjust page pointers in the DVI file
177 dviFile
->size_of_file
= dviFile
->size_of_file
+ lengthOfNewSpecial
-lengthOfOldSpecial
;
178 end_pointer
= newDVI
.data() + dviFile
->size_of_file
;
179 quint32 currentOffset
= beginningOfSpecialCommand
-dviFile
->dvi_Data();
180 for(int i
=0; i
< dviFile
->total_pages
; i
++) {
181 if (dviFile
->page_offset
[i
] > currentOffset
) {
182 dviFile
->page_offset
[i
] = dviFile
->page_offset
[i
] + lengthOfNewSpecial
-lengthOfOldSpecial
;
183 command_pointer
= dviFile
->page_offset
[i
] + newDVI
.data() + 4*10 + 1;
184 quint32 a
= readUINT32();
185 if (a
> currentOffset
) {
186 a
= a
+ lengthOfNewSpecial
-lengthOfOldSpecial
;
187 command_pointer
= dviFile
->page_offset
[i
] + newDVI
.data() + 4*10 + 1;
193 dviFile
->beginning_of_postamble
= dviFile
->beginning_of_postamble
+ lengthOfNewSpecial
- lengthOfOldSpecial
;
194 dviFile
->page_offset
[int(dviFile
->total_pages
)] = dviFile
->beginning_of_postamble
;
196 command_pointer
= newDVI
.data() + dviFile
->beginning_of_postamble
+ 1;
197 quint32 a
= readUINT32();
198 if (a
> currentOffset
) {
199 a
= a
+ lengthOfNewSpecial
- lengthOfOldSpecial
;
200 command_pointer
= newDVI
.data() + dviFile
->beginning_of_postamble
+ 1;
204 command_pointer
= newDVI
.data() + dviFile
->size_of_file
- 1;
205 while((*command_pointer
== TRAILER
) && (command_pointer
> newDVI
.data()))
207 command_pointer
-= 4;
208 writeUINT32(dviFile
->beginning_of_postamble
);
209 command_pointer
-= 4;
211 command_pointer
= commandPtrSav
;
212 end_pointer
= endPtrSav
;
214 // Modify all pointers to point to the newly allocated memory
215 command_pointer
= newDVI
.data() + (command_pointer
- dviFile
->dvi_Data()) + lengthOfNewSpecial
-lengthOfOldSpecial
;
216 end_pointer
= newDVI
.data() + (end_pointer
- dviFile
->dvi_Data()) + lengthOfNewSpecial
-lengthOfOldSpecial
;
218 dviFile
->setNewData(newDVI
);
220 embedPS_progress
->progressBar()->setValue(embedPS_progress
->progressBar()->value()+1);
221 qApp
->processEvents();
226 void dviRenderer::prescan_removePageSizeInfo(char *cp
, quint8
*beginningOfSpecialCommand
)
229 kDebug(kvs::dvi
) << "dviRenderer::prescan_embedPS( cp = " << cp
<< " ) ";
232 // Encapsulated Postscript File
233 if (strncasecmp(cp
, "papersize=", 10) != 0)
236 for (quint8
*ptr
=beginningOfSpecialCommand
; ptr
<command_pointer
; ptr
++)
241 void dviRenderer::prescan_ParsePapersizeSpecial(const QString
& _cp
)
244 kDebug(kvs::dvi
) << "Papersize-Special : papersize" << _cp
;
247 QString cp
= _cp
.simplified();
251 dviFile
->suggestedPageSize
= new pageSize
;
252 dviFile
->suggestedPageSize
->setPageSize(cp
);
254 printErrorMsgForSpecials(i18n("The papersize data '%1' could not be parsed.", cp
));
260 void dviRenderer::prescan_ParseBackgroundSpecial(const QString
& cp
)
262 QColor col
= parseColorSpecification(cp
.trimmed());
264 for(quint16 page
=current_page
; page
< dviFile
->total_pages
; page
++)
265 PS_interface
->setBackgroundColor(page
, col
);
270 void dviRenderer::prescan_ParseHTMLAnchorSpecial(const QString
& _cp
)
273 cp
.truncate(cp
.indexOf('"'));
275 l
.setLength_in_inch(currinf
.data
.dvi_v
/(resolutionInDPI
*shrinkfactor
));
276 anchorList
[cp
] = Anchor(current_page
+1, l
);
280 void dviRenderer::prescan_ParsePSHeaderSpecial(const QString
& cp
)
283 kDebug(kvs::dvi
) << "PostScript-special, header " << cp
.latin1();
288 // If the file is not found in the current directory, use kpsewhich
290 if (!QFile::exists(_file
)) {
291 // Otherwise, use kpsewhich to find the eps file.
293 proc
<< "kpsewhich" << cp
;
294 proc
.setOutputChannelMode(KProcess::SeparateChannels
);
296 _file
= QString::fromLocal8Bit(proc
.readLine().trimmed());
299 if (QFile::exists(_file
))
300 PS_interface
->PostScriptHeaderString
->append( QString(" (%1) run\n").arg(_file
) );
304 void dviRenderer::prescan_ParsePSBangSpecial(const QString
& cp
)
307 kDebug(kvs::dvi
) << "PostScript-special, literal header " << cp
.latin1();
310 PS_interface
->PostScriptHeaderString
->append( " @defspecial \n" );
311 PS_interface
->PostScriptHeaderString
->append( cp
);
312 PS_interface
->PostScriptHeaderString
->append( " @fedspecial \n" );
316 void dviRenderer::prescan_ParsePSQuoteSpecial(const QString
& cp
)
319 kError(kvs::dvi
) << "PostScript-special, literal PostScript " << cp
.latin1() << endl
;
322 double PS_H
= (currinf
.data
.dvi_h
*300.0)/(65536*1200)-300;
323 double PS_V
= (currinf
.data
.dvi_v
*300.0)/1200 - 300;
324 PostScriptOutPutString
->append( QString(" %1 %2 moveto\n").arg(PS_H
).arg(PS_V
) );
325 PostScriptOutPutString
->append( " @beginspecial @setspecial \n" );
326 PostScriptOutPutString
->append( cp
);
327 PostScriptOutPutString
->append( " @endspecial \n" );
331 void dviRenderer::prescan_ParsePSSpecial(const QString
& cp
)
334 kDebug(kvs::dvi
) << "PostScript-special, direct PostScript " << cp
;
337 // Unfortunately, in some TeX distribution the hyperref package uses
338 // the dvips driver by default, rather than the hypertex driver. As
339 // a result, the DVI files produced are full of PostScript that
340 // specifies links and anchors, and KDVI would call the ghostscript
341 // interpreter for every page which makes it really slow. This is a
342 // major nuisance, so that we try to filter and interpret the
343 // hypertex generated PostScript here.
344 if (cp
.startsWith("ps:SDict begin")) {
345 // We suspect this may be hyperref generated nonsense. Let's check
346 // for some known code that hyperref generates.
347 if (cp
== "ps:SDict begin H.S end")
348 return; // start of hyperref rectangle
349 if (cp
== "ps:SDict begin H.R end")
350 return; // end of hyperref rectangle
351 if (cp
.endsWith("H.A end"))
352 return; // end of hyperref anchor
353 if (cp
.endsWith("H.L end"))
354 return; // end of hyperref link
355 if (cp
.startsWith("ps:SDict begin /product where{pop product(Distiller)"))
356 return; // hyperref tries to work around Distiller bug
357 if (cp
.startsWith("ps:SDict begin [") && cp
.endsWith(" pdfmark end")) { // hyperref definition of link/anchor/bookmark/etc
358 if (cp
.contains("/DEST")) { // The PostScript code defines an anchor
359 QString anchorName
= cp
.section('(', 1, 1).section(')', 0, 0);
361 l
.setLength_in_inch(currinf
.data
.dvi_v
/(resolutionInDPI
*shrinkfactor
));
362 anchorList
[anchorName
] = Anchor(current_page
+1, l
);
364 // The PostScript code defines a bookmark
365 if (cp
.contains("/Dest") && cp
.contains("/Title"))
366 prebookmarks
.append(PreBookmark(PDFencodingToQString(cp
.section('(', 2, 2).section(')', 0, 0)),
367 cp
.section('(', 1, 1).section(')', 0, 0),
368 cp
.section('-', 1, 1).section(' ', 0, 0).toUInt()
374 double PS_H
= (currinf
.data
.dvi_h
*300.0)/(65536*1200)-300;
375 double PS_V
= (currinf
.data
.dvi_v
*300.0)/1200 - 300;
377 if (cp
.indexOf("ps::[begin]", 0, Qt::CaseInsensitive
) == 0) {
378 PostScriptOutPutString
->append( QString(" %1 %2 moveto\n").arg(PS_H
).arg(PS_V
) );
379 PostScriptOutPutString
->append( QString(" %1\n").arg(cp
.mid(11)) );
381 if (cp
.indexOf("ps::[end]", 0, Qt::CaseInsensitive
) == 0) {
382 PostScriptOutPutString
->append( QString(" %1\n").arg(cp
.mid(9)) );
384 if (cp
.indexOf("ps::", 0, Qt::CaseInsensitive
) == 0) {
385 PostScriptOutPutString
->append( QString(" %1\n").arg(cp
.mid(4)) );
387 PostScriptOutPutString
->append( QString(" %1 %2 moveto\n").arg(PS_H
).arg(PS_V
) );
388 PostScriptOutPutString
->append( QString(" %1\n").arg(cp
.mid(3)) );
395 void dviRenderer::prescan_ParsePSFileSpecial(const QString
& cp
)
398 kDebug(kvs::dvi
) << "epsf-special: psfile=" << cp
;
401 QString include_command
= cp
.simplified();
403 // The line is supposed to start with "..ile=", and then comes the
404 // filename. Figure out what the filename is and stow it away. Of
405 // course, this does not work if the filename contains spaces
406 // (already the simplified() above is wrong). If you have
407 // files like this, go away.
408 QString EPSfilename
= include_command
;
409 EPSfilename
.truncate(EPSfilename
.indexOf(' '));
411 // Strip enclosing quotation marks which are included by some LaTeX
412 // macro packages (but not by others). This probably means that
413 // graphic files are no longer found if the filename really does
414 // contain quotes, but we don't really care that much.
415 if ((EPSfilename
.at(0) == '\"') && (EPSfilename
.at(EPSfilename
.length()-1) == '\"')) {
416 EPSfilename
= EPSfilename
.mid(1,EPSfilename
.length()-2);
419 // If the file name ends in 'png', 'gif', 'jpg' or 'jpeg', we assume
420 // that this is NOT a PostScript file, and we exit here.
421 QString ending
= EPSfilename
.section('.', -1).toLower();
422 if ((ending
== "png") || (ending
== "gif") || (ending
== "jpg") || (ending
== "jpeg")) {
423 dviFile
->numberOfExternalNONPSFiles
++;
427 // Now assume that the graphics file *is* a PostScript file
428 dviFile
->numberOfExternalPSFiles
++;
430 // Now locate the Gfx file on the hard disk...
431 EPSfilename
= ghostscript_interface::locateEPSfile(EPSfilename
, baseURL
);
433 // If the EPSfilename really points to a PDF file, convert that file now.
434 if (ending
== "pdf") {
435 QString convErrorMsg
;
436 QString oEPSfilename
= EPSfilename
;
437 //emit setStatusBarText( i18n("Converting PDF-file %1...", EPSfilename) );
438 EPSfilename
= dviFile
->convertPDFtoPS(EPSfilename
, &convErrorMsg
);
439 //emit setStatusBarText( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
440 if (convErrorMsg
.isEmpty() != true) {
441 /* KMessageBox::detailedError(parentWidget,
442 i18n("<qt><strong>File conversion error</strong> KDVI was not able to convert the external "
443 "PDF file <strong>%1</strong> into PostScript. Expect missing graphics or graphic errors.</qt>", oEPSfilename),
444 convErrorMsg, i18n("PDF/PS conversion error"));*/
449 // Now parse the arguments.
458 // just to avoid ambiguities; the filename could contain keywords
459 include_command
= include_command
.mid(include_command
.indexOf(' '));
461 parse_special_argument(include_command
, "llx=", &llx
);
462 parse_special_argument(include_command
, "lly=", &lly
);
463 parse_special_argument(include_command
, "urx=", &urx
);
464 parse_special_argument(include_command
, "ury=", &ury
);
465 parse_special_argument(include_command
, "rwi=", &rwi
);
466 parse_special_argument(include_command
, "rhi=", &rhi
);
467 parse_special_argument(include_command
, "angle=", &angle
);
469 int clip
=include_command
.indexOf(" clip"); // -1 if clip keyword is not present, >= 0 otherwise
471 if (QFile::exists(EPSfilename
)) {
472 double PS_H
= (currinf
.data
.dvi_h
*300.0)/(65536*1200)-300;
473 double PS_V
= (currinf
.data
.dvi_v
*300.0)/1200 - 300;
474 PostScriptOutPutString
->append( QString(" %1 %2 moveto\n").arg(PS_H
).arg(PS_V
) );
475 PostScriptOutPutString
->append( "@beginspecial " );
476 PostScriptOutPutString
->append( QString(" %1 @llx").arg(llx
) );
477 PostScriptOutPutString
->append( QString(" %1 @lly").arg(lly
) );
478 PostScriptOutPutString
->append( QString(" %1 @urx").arg(urx
) );
479 PostScriptOutPutString
->append( QString(" %1 @ury").arg(ury
) );
481 PostScriptOutPutString
->append( QString(" %1 @rwi").arg(rwi
) );
483 PostScriptOutPutString
->append( QString(" %1 @rhi").arg(rhi
) );
485 PostScriptOutPutString
->append( QString(" %1 @angle").arg(angle
) );
487 PostScriptOutPutString
->append(" @clip");
488 PostScriptOutPutString
->append( " @setspecial \n" );
489 PostScriptOutPutString
->append( QString(" (%1) run\n").arg(EPSfilename
) );
490 PostScriptOutPutString
->append( "@endspecial \n" );
497 void dviRenderer::prescan_ParseSourceSpecial(const QString
& cp
)
499 // if no rendering takes place, i.e. when the DVI file is first
500 // loaded, generate a DVI_SourceFileAnchor. These anchors are used
501 // in forward search, i.e. to relate references line
502 // "src:123file.tex" to positions in the DVI file
504 // extract the file name and the numeral part from the string
506 for(j
=0;j
<cp
.length();j
++)
507 if (!cp
.at(j
).isNumber())
509 quint32 sourceLineNumber
= cp
.left(j
).toUInt();
510 QFileInfo
fi1(dviFile
->filename
);
511 QString sourceFileName
= QFileInfo(fi1
.dir(), cp
.mid(j
).trimmed()).absoluteFilePath();
513 l
.setLength_in_inch(currinf
.data
.dvi_v
/(resolutionInDPI
*shrinkfactor
));
514 DVI_SourceFileAnchor
sfa(sourceFileName
, sourceLineNumber
, current_page
+1, l
);
515 sourceHyperLinkAnchors
.push_back(sfa
);
519 void dviRenderer::prescan_parseSpecials(char *cp
, quint8
*)
521 QString
special_command(cp
);
523 // Now to those specials which are only interpreted during the
524 // prescan phase, and NOT during rendering.
527 if (strncasecmp(cp
, "papersize", 9) == 0) {
528 prescan_ParsePapersizeSpecial(special_command
.mid(9));
532 // color special for background color
533 if (strncasecmp(cp
, "background", 10) == 0) {
534 prescan_ParseBackgroundSpecial(special_command
.mid(10));
538 // HTML anchor special
539 if (strncasecmp(cp
, "html:<A name=", 13) == 0) {
540 prescan_ParseHTMLAnchorSpecial(special_command
.mid(14));
544 // Postscript Header File
545 if (strncasecmp(cp
, "header=", 7) == 0) {
546 prescan_ParsePSHeaderSpecial(special_command
.mid(7));
550 // Literal Postscript Header
552 prescan_ParsePSBangSpecial(special_command
.mid(1));
556 // Literal Postscript inclusion
558 prescan_ParsePSQuoteSpecial(special_command
.mid(1));
562 // PS-Postscript inclusion
563 if (strncasecmp(cp
, "ps:", 3) == 0) {
564 prescan_ParsePSSpecial(special_command
);
568 // Encapsulated Postscript File
569 if (strncasecmp(cp
, "PSfile=", 7) == 0) {
570 prescan_ParsePSFileSpecial(special_command
.mid(7));
575 if (strncasecmp(cp
, "src:", 4) == 0) {
576 prescan_ParseSourceSpecial(special_command
.mid(4));
580 // Finally there are those special commands which must be considered
581 // both during rendering and during the pre-scan phase
584 if (strncasecmp(cp
, "html:</A>", 9) == 0) {
593 void dviRenderer::prescan_setChar(unsigned int ch
)
595 TeXFontDefinition
*fontp
= currinf
.fontp
;
599 if (currinf
.set_char_p
== &dviRenderer::set_char
) {
600 glyph
*g
= ((TeXFont
*)(currinf
.fontp
->font
))->getGlyph(ch
, true, globalColor
);
603 currinf
.data
.dvi_h
+= (int)(currinf
.fontp
->scaled_size_in_DVI_units
* dviFile
->getCmPerDVIunit() *
604 (1200.0 / 2.54)/16.0 * g
->dvi_advance_in_units_of_design_size_by_2e20
+ 0.5);
608 if (currinf
.set_char_p
== &dviRenderer::set_vf_char
) {
609 macro
*m
= &currinf
.fontp
->macrotable
[ch
];
612 currinf
.data
.dvi_h
+= (int)(currinf
.fontp
->scaled_size_in_DVI_units
* dviFile
->getCmPerDVIunit() *
613 (1200.0 / 2.54)/16.0 * m
->dvi_advance_in_units_of_design_size_by_2e20
+ 0.5);
619 void dviRenderer::prescan(parseSpecials specialParser
)
622 kDebug(kvs::dvi
) << "dviRenderer::prescan( ... )";
625 if (resolutionInDPI
== 0.0)
628 qint32 RRtmp
=0, WWtmp
=0, XXtmp
=0, YYtmp
=0, ZZtmp
=0;
630 double fontPixelPerDVIunit
= dviFile
->getCmPerDVIunit() * 1200.0/2.54;
634 currinf
.fontp
= NULL
;
635 currinf
.set_char_p
= &dviRenderer::set_no_char
;
640 if (ch
<= (unsigned char) (SETCHAR0
+ 127)) {
645 if (FNTNUM0
<= ch
&& ch
<= (unsigned char) (FNTNUM0
+ 63)) {
646 currinf
.fontp
= currinf
.fonttable
->find(ch
- FNTNUM0
);
647 if (currinf
.fontp
== NULL
) {
648 errorMsg
= i18n("The DVI code referred to font #%1, which was not previously defined.", ch
- FNTNUM0
);
651 currinf
.set_char_p
= currinf
.fontp
->set_char_p
;
660 prescan_setChar(readUINT8());
664 /* Be careful, dvicopy outputs rules with height =
665 0x80000000. We don't want any SIGFPE here. */
668 b
= ((long) (b
* 65536.0*fontPixelPerDVIunit
));
669 currinf
.data
.dvi_h
+= b
;
682 command_pointer
+= 11 * 4;
683 currinf
.data
.dvi_h
= 1200 << 16; // Reminder: DVI-coordinates start at (1",1") from top of page
684 currinf
.data
.dvi_v
= 1200;
685 currinf
.data
.pxl_v
= int(currinf
.data
.dvi_v
/shrinkfactor
);
686 currinf
.data
.w
= currinf
.data
.x
= currinf
.data
.y
= currinf
.data
.z
= 0;
690 stack
.push(currinf
.data
);
697 currinf
.data
= stack
.pop();
704 RRtmp
= readINT(ch
- RIGHT1
+ 1);
705 currinf
.data
.dvi_h
+= ((long) (RRtmp
* 65536.0*fontPixelPerDVIunit
));
712 WWtmp
= readINT(ch
- W0
);
713 currinf
.data
.w
= ((long) (WWtmp
* 65536.0*fontPixelPerDVIunit
));
715 currinf
.data
.dvi_h
+= currinf
.data
.w
;
722 XXtmp
= readINT(ch
- X0
);
723 currinf
.data
.x
= ((long) (XXtmp
* 65536.0*fontPixelPerDVIunit
));
725 currinf
.data
.dvi_h
+= currinf
.data
.x
;
733 qint32 DDtmp
= readINT(ch
- DOWN1
+ 1);
734 currinf
.data
.dvi_v
+= ((long) (DDtmp
* 65536.0*fontPixelPerDVIunit
))/65536;
735 currinf
.data
.pxl_v
= int(currinf
.data
.dvi_v
/shrinkfactor
);
743 YYtmp
= readINT(ch
- Y0
);
744 currinf
.data
.y
= ((long) (YYtmp
* 65536.0*fontPixelPerDVIunit
));
746 currinf
.data
.dvi_v
+= currinf
.data
.y
/65536;
747 currinf
.data
.pxl_v
= int(currinf
.data
.dvi_v
/shrinkfactor
);
754 ZZtmp
= readINT(ch
- Z0
);
755 currinf
.data
.z
= ((long) (ZZtmp
* 65536.0*fontPixelPerDVIunit
));
757 currinf
.data
.dvi_v
+= currinf
.data
.z
/65536;
758 currinf
.data
.pxl_v
= int(currinf
.data
.dvi_v
/shrinkfactor
);
765 currinf
.fontp
= currinf
.fonttable
->find(readUINT(ch
- FNT1
+ 1));
766 if (currinf
.fontp
== NULL
)
768 currinf
.set_char_p
= currinf
.fontp
->set_char_p
;
776 quint8
*beginningOfSpecialCommand
= command_pointer
-1;
777 a
= readUINT(ch
- XXX1
+ 1);
779 char *cmd
= new char[a
+1];
780 strncpy(cmd
, (char *)command_pointer
, a
);
781 command_pointer
+= a
;
783 (this->*specialParser
)(cmd
, beginningOfSpecialCommand
);
793 command_pointer
+= 12 + ch
- FNTDEF1
+ 1;
794 command_pointer
+= readUINT8() + readUINT8();