mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-25 02:45:38 +00:00
improved glyph rendering for PK fonts
svn path=/trunk/kdegraphics/kdvi/; revision=220816
This commit is contained in:
parent
9b97c8d979
commit
0eb0c5e7a1
4
TODO
4
TODO
|
@ -2,9 +2,9 @@ ToDo-List for kdvi
|
|||
|
||||
URGENT / URGENT BUGFIXING
|
||||
|
||||
o Checksum mismatches in all PK files
|
||||
o SGA1.dvi-novirtual läuft nicht mehr!
|
||||
o Bad display of virtual font ligatures
|
||||
o implement background according to DVIPS specifications, make it work is there is PS on the page
|
||||
o implement background according to DVIPS specifications, make it work if there is PS on the page
|
||||
o improve performance and perceived performance (see also under 'highly desirable')
|
||||
|
||||
o add "papersize" which does not display the margin
|
||||
|
|
211
TeXFont_PK.cpp
211
TeXFont_PK.cpp
|
@ -51,6 +51,7 @@
|
|||
|
||||
#include <kdebug.h>
|
||||
#include <klocale.h>
|
||||
#include <math.h>
|
||||
#include <qbitmap.h>
|
||||
#include <qfile.h>
|
||||
#include <qimage.h>
|
||||
|
@ -173,72 +174,105 @@ glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor co
|
|||
// a pixel. That doesn't sound much, but on low-resolution
|
||||
// devices, such as a notebook screen, the effect would be a
|
||||
// "dancing line" of characters, which looks really bad.
|
||||
//
|
||||
// The cure is the following procedure:
|
||||
//
|
||||
// (a) scale the hot point
|
||||
//
|
||||
// (b) fit the unshrunken bitmap into a bitmap which is even
|
||||
// bigger. Use this to produce extra empty rows and columns at the
|
||||
// borders. The proper choice of the border size will ensure that
|
||||
// the hot point will fall exactly onto the coordinates which we
|
||||
// calculated previously.
|
||||
|
||||
// Calculate the coordinates of the hot point in the shrunken
|
||||
// bitmap
|
||||
g->x2 = (int)(g->x/shrinkFactor);
|
||||
g->y2 = (int)(g->y/shrinkFactor);
|
||||
|
||||
// Calculate the size of the target bitmap for the
|
||||
int shrunk_width = g->x2 + (int)((characterBitmaps[ch]->w - g->x) / shrinkFactor + 0.5) + 1;
|
||||
int shrunk_height = g->y2 + (int)((characterBitmaps[ch]->h - g->y) / shrinkFactor + 0.5) + 1;
|
||||
|
||||
// Now calculate the size of the white border. This is some sort
|
||||
// of black magic. Don't modify unless you know what you are doing.
|
||||
int pre_rows = (int)((1.0 + g->y2)*shrinkFactor + 0.5) - g->y - 1;
|
||||
if (pre_rows < 0)
|
||||
pre_rows = 0;
|
||||
int post_rows = (int)(shrunk_height*shrinkFactor + 0.5) - characterBitmaps[ch]->h;
|
||||
if (post_rows < 0)
|
||||
post_rows = 0;
|
||||
|
||||
int pre_cols = (int)((1.0 + g->x2)*shrinkFactor + 0.5) - g->x - 1;
|
||||
if (pre_cols < 0)
|
||||
pre_cols = 0;
|
||||
int post_cols = (int)(shrunk_width*shrinkFactor + 0.5) - characterBitmaps[ch]->w;
|
||||
if (post_cols < 0)
|
||||
post_cols = 0;
|
||||
|
||||
// Now shrinking may begin. Produce a QBitmap with the unshrunk
|
||||
// character.
|
||||
QBitmap bm(characterBitmaps[ch]->bytes_wide*8, (int)characterBitmaps[ch]->h, (const uchar *)(characterBitmaps[ch]->bits), TRUE);
|
||||
// ... turn it into a Pixmap (highly inefficient, please improve)
|
||||
QPixmap intpm(characterBitmaps[ch]->w + pre_cols+post_cols, characterBitmaps[ch]->h + pre_rows+post_rows);
|
||||
QPainter paint(&intpm);
|
||||
paint.setBackgroundColor(Qt::white);
|
||||
paint.setPen( Qt::black );
|
||||
paint.fillRect(0,0,characterBitmaps[ch]->w + pre_cols+post_cols, characterBitmaps[ch]->h + pre_rows+post_rows, Qt::white);
|
||||
paint.drawPixmap(pre_cols, pre_rows, bm);
|
||||
paint.end();
|
||||
|
||||
// Generate an Image and shrink it to the proper size. By the
|
||||
// documentation of smoothScale, the resulting Image will be
|
||||
// 8-bit.
|
||||
QImage EightBitImage = intpm.convertToImage().smoothScale(shrunk_width, shrunk_height).convertDepth(32);
|
||||
// bitmap. For simplicity, let us consider the x-coordinate
|
||||
// first. In principle, the hot point should have an x-coordinate
|
||||
// of (g->x/shrinkFactor). That, however, will generally NOT be an
|
||||
// integral number. The cure is to translate the source image
|
||||
// somewhat, so that the x-coordinate of the hot point falls onto
|
||||
// the round-up of this number, i.e.
|
||||
g->x2 = (int)ceil(g->x/shrinkFactor);
|
||||
|
||||
// Translating and scaling then means that the pixel in the scaled
|
||||
// image which covers the range [x,x+1) corresponds to the range
|
||||
// [x*shrinkFactor+srcXTrans, (x+1)*shrinkFactor+srcXTrans), where
|
||||
// srcXTrans is the following NEGATIVE number
|
||||
double srcXTrans = g->x/shrinkFactor - ceil(g->x/shrinkFactor);
|
||||
|
||||
// How big will the shrunken bitmap then become? If shrunk_width
|
||||
// denotes that width of the scaled image, and
|
||||
// characterBitmaps[ch]->w the width of the orininal image, we
|
||||
// need to make sure that the following inequality holds:
|
||||
//
|
||||
// shrunk_width*shrinkFactor+srcXTrans >= characterBitmaps[ch]->w
|
||||
//
|
||||
// in other words,
|
||||
int shrunk_width = (int)ceil( (characterBitmaps[ch]->w - srcXTrans)/shrinkFactor );
|
||||
|
||||
// Now do the same for the y-coordinate
|
||||
g->y2 = (int)ceil(g->y/shrinkFactor);
|
||||
double srcYTrans = g->y/shrinkFactor - ceil(g->y/shrinkFactor);
|
||||
int shrunk_height = (int)ceil( (characterBitmaps[ch]->h - srcYTrans)/shrinkFactor );
|
||||
|
||||
// Turn the image into 8 bit
|
||||
QByteArray translated(characterBitmaps[ch]->w * characterBitmaps[ch]->h);
|
||||
Q_UINT8 *data = (Q_UINT8 *)translated.data();
|
||||
for(int x=0; x<characterBitmaps[ch]->w; x++)
|
||||
for(int y=0; y<characterBitmaps[ch]->h; y++) {
|
||||
Q_UINT8 bit = *(characterBitmaps[ch]->bits + characterBitmaps[ch]->bytes_wide*y + (x >> 3));
|
||||
bit = bit >> (x & 7);
|
||||
bit = bit & 1;
|
||||
data[characterBitmaps[ch]->w*y + x] = bit;
|
||||
}
|
||||
|
||||
// Now shrink the image. We shrink the X-direction first
|
||||
QByteArray xshrunk(shrunk_width*characterBitmaps[ch]->h);
|
||||
Q_UINT8 *xdata = (Q_UINT8 *)xshrunk.data();
|
||||
|
||||
// Do the shrinking. The pixel (x,y) that we want to calculate
|
||||
// corresponds to the line segment from
|
||||
//
|
||||
// [shrinkFactor*x+srcXTrans, shrinkFactor*(x+1)+srcXTrans)
|
||||
//
|
||||
// The trouble is, these numbers are in general no integers.
|
||||
|
||||
for(int y=0; y<characterBitmaps[ch]->h; y++)
|
||||
for(int x=0; x<shrunk_width; x++) {
|
||||
Q_UINT32 value = 0;
|
||||
double destStartX = shrinkFactor*x+srcXTrans;
|
||||
double destEndX = shrinkFactor*(x+1)+srcXTrans;
|
||||
for(int srcX=(int)ceil(destStartX); srcX<floor(destEndX); srcX++)
|
||||
if ((srcX >= 0) && (srcX < characterBitmaps[ch]->w))
|
||||
value += data[characterBitmaps[ch]->w*y + srcX] * 255;
|
||||
|
||||
if (destStartX >= 0.0)
|
||||
value += 255.0*(ceil(destStartX)-destStartX) * data[characterBitmaps[ch]->w*y + (int)floor(destStartX)];
|
||||
if (floor(destEndX) < characterBitmaps[ch]->w)
|
||||
value += 255.0*(destEndX-floor(destEndX)) * data[characterBitmaps[ch]->w*y + (int)floor(destEndX)];
|
||||
|
||||
xdata[shrunk_width*y + x] = (int)( value/shrinkFactor + 0.5);
|
||||
}
|
||||
|
||||
// Now shrink the Y-direction
|
||||
QByteArray xyshrunk(shrunk_width*shrunk_height);
|
||||
Q_UINT8 *xydata = (Q_UINT8 *)xyshrunk.data();
|
||||
for(int x=0; x<shrunk_width; x++)
|
||||
for(int y=0; y<shrunk_height; y++) {
|
||||
Q_UINT32 value = 0;
|
||||
double destStartY = shrinkFactor*y+srcYTrans;
|
||||
double destEndY = shrinkFactor*(y+1)+srcYTrans;
|
||||
for(int srcY=(int)ceil(destStartY); srcY<floor(destEndY); srcY++)
|
||||
if ((srcY >= 0) && (srcY < characterBitmaps[ch]->h))
|
||||
value += xdata[shrunk_width*srcY + x];
|
||||
|
||||
if (destStartY >= 0.0)
|
||||
value += (ceil(destStartY)-destStartY) * xdata[shrunk_width*(int)floor(destStartY) + x];
|
||||
if (floor(destEndY) < characterBitmaps[ch]->h)
|
||||
value += (destEndY-floor(destEndY)) * xdata[shrunk_width*(int)floor(destEndY) + x];
|
||||
|
||||
xydata[shrunk_width*y + x] = (int)(value/shrinkFactor);
|
||||
}
|
||||
|
||||
// Generate the alpha-channel. This again is highly inefficient.
|
||||
// Would anybody please produce a faster routine?
|
||||
QImage im32(shrunk_width, shrunk_height, 32);
|
||||
im32.fill(qRgb(color.red(), color.green(), color.blue()));
|
||||
im32.setAlphaBuffer(TRUE);
|
||||
for(Q_UINT16 y=0; y<shrunk_height; y++) {
|
||||
Q_UINT8 *srcScanLine = (Q_UINT8 *)EightBitImage.scanLine(y);
|
||||
Q_UINT8 *destScanLine = (Q_UINT8 *)im32.scanLine(y);
|
||||
for(Q_UINT16 col=0; col<shrunk_width; col++) {
|
||||
destScanLine[4*col+0] = color.blue();
|
||||
destScanLine[4*col+1] = color.green();
|
||||
destScanLine[4*col+2] = color.red();
|
||||
destScanLine[4*col+3] = 0xFF-srcScanLine[4*col];
|
||||
}
|
||||
for(Q_UINT16 col=0; col<shrunk_width; col++)
|
||||
destScanLine[4*col+3] = xydata[shrunk_width*y + col];
|
||||
}
|
||||
g->shrunkenCharacter.convertFromImage(im32,0);
|
||||
g->shrunkenCharacter.setOptimization(QPixmap::BestOptim);
|
||||
|
@ -247,12 +281,9 @@ glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor co
|
|||
}
|
||||
|
||||
|
||||
#define BMUNIT Q_UINT32
|
||||
#define BITS_PER_BMUNIT 32
|
||||
#define BYTES_PER_BMUNIT 4
|
||||
|
||||
#define ADD(a, b) ((BMUNIT *) (((char *) a) + b))
|
||||
#define SUB(a, b) ((BMUNIT *) (((char *) a) - b))
|
||||
#define ADD(a, b) ((Q_UINT32 *) (((char *) a) + b))
|
||||
#define SUB(a, b) ((Q_UINT32 *) (((char *) a) - b))
|
||||
|
||||
|
||||
|
||||
|
@ -278,7 +309,7 @@ static const uchar bitflip[256] = {
|
|||
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
|
||||
};
|
||||
|
||||
static BMUNIT bit_masks[33] = {
|
||||
static Q_UINT32 bit_masks[33] = {
|
||||
0x0, 0x1, 0x3, 0x7,
|
||||
0xf, 0x1f, 0x3f, 0x7f,
|
||||
0xff, 0x1ff, 0x3ff, 0x7ff,
|
||||
|
@ -408,11 +439,11 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
int n;
|
||||
int row_bit_pos;
|
||||
bool paint_switch;
|
||||
BMUNIT *cp;
|
||||
Q_UINT32 *cp;
|
||||
register struct glyph *g;
|
||||
register FILE *fp = file;
|
||||
long fpwidth;
|
||||
BMUNIT word = 0;
|
||||
Q_UINT32 word = 0;
|
||||
int word_weight, bytes_wide;
|
||||
int rows_left, h_bit, count;
|
||||
|
||||
|
@ -463,21 +494,21 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
|
||||
{
|
||||
/* width must be multiple of 16 bits for raster_op */
|
||||
characterBitmaps[ch]->bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
|
||||
characterBitmaps[ch]->bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, 32) * 4;
|
||||
register unsigned int size = characterBitmaps[ch]->bytes_wide * characterBitmaps[ch]->h;
|
||||
characterBitmaps[ch]->bits = new char[size != 0 ? size : 1];
|
||||
}
|
||||
|
||||
cp = (BMUNIT *) characterBitmaps[ch]->bits;
|
||||
cp = (Q_UINT32 *) characterBitmaps[ch]->bits;
|
||||
|
||||
/*
|
||||
* read character data into *cp
|
||||
*/
|
||||
bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
|
||||
bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, 32) * 4;
|
||||
PK_bitpos = -1;
|
||||
|
||||
// The routines which read the character depend on the byte
|
||||
// ordering. In principle, the byte order should be detected at
|
||||
// The routines which read the character depend on the bit
|
||||
// ordering. In principle, the bit order should be detected at
|
||||
// compile time and the proper routing chosen. For the moment, as
|
||||
// autoconf is somewhat complicated for the author, we prefer a
|
||||
// simpler -even if somewhat slower approach and detect the ordering
|
||||
|
@ -499,7 +530,7 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
memset(characterBitmaps[ch]->bits, 0, (int) characterBitmaps[ch]->h * bytes_wide);
|
||||
for (i = 0; i < (int) characterBitmaps[ch]->h; i++) { /* get all rows */
|
||||
cp = ADD(characterBitmaps[ch]->bits, i * bytes_wide);
|
||||
row_bit_pos = BITS_PER_BMUNIT;
|
||||
row_bit_pos = 32;
|
||||
for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
|
||||
if (--PK_bitpos < 0) {
|
||||
word = one(fp);
|
||||
|
@ -507,7 +538,7 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
}
|
||||
if (--row_bit_pos < 0) {
|
||||
cp++;
|
||||
row_bit_pos = BITS_PER_BMUNIT - 1;
|
||||
row_bit_pos = 32 - 1;
|
||||
}
|
||||
if (word & (1 << PK_bitpos))
|
||||
*cp |= 1 << row_bit_pos;
|
||||
|
@ -517,7 +548,7 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
rows_left = characterBitmaps[ch]->h;
|
||||
h_bit = characterBitmaps[ch]->w;
|
||||
PK_repeat_count = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
word = 0;
|
||||
while (rows_left > 0) {
|
||||
count = PK_packed_num(fp);
|
||||
|
@ -534,15 +565,14 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
word |= bit_masks[h_bit] << (word_weight - h_bit);
|
||||
*cp++ = word;
|
||||
/* "output" row(s) */
|
||||
for (i = PK_repeat_count * bytes_wide /
|
||||
BYTES_PER_BMUNIT; i > 0; --i) {
|
||||
for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
|
||||
*cp = *SUB(cp, bytes_wide);
|
||||
++cp;
|
||||
}
|
||||
rows_left -= PK_repeat_count + 1;
|
||||
PK_repeat_count = 0;
|
||||
word = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
count -= h_bit;
|
||||
h_bit = characterBitmaps[ch]->w;
|
||||
} else {
|
||||
|
@ -552,17 +582,17 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
word = 0;
|
||||
count -= word_weight;
|
||||
h_bit -= word_weight;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
}
|
||||
}
|
||||
paint_switch = 1 - paint_switch;
|
||||
}
|
||||
if (cp != ((BMUNIT *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
|
||||
if (cp != ((Q_UINT32 *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
|
||||
oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(parent->filename));
|
||||
if (rows_left != 0 || h_bit != characterBitmaps[ch]->w)
|
||||
oops(i18n("Bad pk file (%1), too many bits").arg(parent->filename));
|
||||
}
|
||||
|
||||
|
||||
// The data in the bitmap is now in the processor's bit order,
|
||||
// that is, big endian. Since XWindows needs little endian, we
|
||||
// need to change the bit order now.
|
||||
|
@ -572,9 +602,9 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
*bitmapData = bitflip[*bitmapData];
|
||||
bitmapData++;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
// Routines for small Endian start here. This applies e.g. to
|
||||
// Intel and Alpha processors.
|
||||
|
||||
|
@ -592,7 +622,7 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
word = one(fp);
|
||||
PK_bitpos = 7;
|
||||
}
|
||||
if (++row_bit_pos >= BITS_PER_BMUNIT) {
|
||||
if (++row_bit_pos >= 32) {
|
||||
cp++;
|
||||
row_bit_pos = 0;
|
||||
}
|
||||
|
@ -604,47 +634,46 @@ void TeXFont_PK::read_PK_char(unsigned int ch)
|
|||
rows_left = characterBitmaps[ch]->h;
|
||||
h_bit = characterBitmaps[ch]->w;
|
||||
PK_repeat_count = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
word = 0;
|
||||
while (rows_left > 0) {
|
||||
count = PK_packed_num(fp);
|
||||
while (count > 0) {
|
||||
if (count < word_weight && count < h_bit) {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[count] << (BITS_PER_BMUNIT - word_weight);
|
||||
word |= bit_masks[count] << (32 - word_weight);
|
||||
h_bit -= count;
|
||||
word_weight -= count;
|
||||
count = 0;
|
||||
} else
|
||||
if (count >= h_bit && h_bit <= word_weight) {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[h_bit] << (BITS_PER_BMUNIT - word_weight);
|
||||
word |= bit_masks[h_bit] << (32 - word_weight);
|
||||
*cp++ = word;
|
||||
/* "output" row(s) */
|
||||
for (i = PK_repeat_count * bytes_wide /
|
||||
BYTES_PER_BMUNIT; i > 0; --i) {
|
||||
for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
|
||||
*cp = *SUB(cp, bytes_wide);
|
||||
++cp;
|
||||
}
|
||||
rows_left -= PK_repeat_count + 1;
|
||||
PK_repeat_count = 0;
|
||||
word = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
count -= h_bit;
|
||||
h_bit = characterBitmaps[ch]->w;
|
||||
} else {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[word_weight] << (BITS_PER_BMUNIT - word_weight);
|
||||
word |= bit_masks[word_weight] << (32 - word_weight);
|
||||
*cp++ = word;
|
||||
word = 0;
|
||||
count -= word_weight;
|
||||
h_bit -= word_weight;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word_weight = 32;
|
||||
}
|
||||
}
|
||||
paint_switch = 1 - paint_switch;
|
||||
}
|
||||
if (cp != ((BMUNIT *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
|
||||
if (cp != ((Q_UINT32 *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
|
||||
oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(parent->filename));
|
||||
if (rows_left != 0 || h_bit != characterBitmaps[ch]->w)
|
||||
oops(i18n("Bad pk file (%1), too many bits").arg(parent->filename));
|
||||
|
|
|
@ -68,6 +68,9 @@ dviWindow::dviWindow(double zoom, QWidget *parent, const char *name )
|
|||
setFocus();
|
||||
|
||||
connect( &clearStatusBarTimer, SIGNAL(timeout()), this, SLOT(clearStatusBar()) );
|
||||
|
||||
sourceHyperLinkList.reserve(200);
|
||||
textLinkList.reserve(250);
|
||||
|
||||
// initialize the dvi machinery
|
||||
dviFile = 0;
|
||||
|
@ -369,6 +372,7 @@ void dviWindow::drawPage()
|
|||
else {
|
||||
kdDebug(4300) << "Time required to draw all pages: " << performanceTimer.restart() << "ms" << endl;
|
||||
performanceFlag = 2;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -561,8 +561,13 @@ void dviWindow::draw_page(void)
|
|||
HTML_href = 0;
|
||||
source_href = 0;
|
||||
hyperLinkList.clear();
|
||||
textLinkList.clear();
|
||||
sourceHyperLinkList.clear();
|
||||
|
||||
|
||||
// Calling resize() here rather than clear() means that the memory
|
||||
// taken up by the vector is not freed. This is faster than
|
||||
// constantly allocating/freeing memory.
|
||||
textLinkList.resize(0);
|
||||
sourceHyperLinkList.resize(0);
|
||||
|
||||
// Check if all the fonts are loaded. If that is not the case, we
|
||||
// return and do not draw anything. The font_pool will later emit
|
||||
|
@ -577,7 +582,6 @@ void dviWindow::draw_page(void)
|
|||
// it. Set the flag so that is message will not be printed again.
|
||||
if (performanceFlag == 0) {
|
||||
kdDebug(4300) << "Time elapsed till the first page is drawn: " << performanceTimer.restart() << "ms" << endl;
|
||||
exit(0);
|
||||
performanceFlag = 1;
|
||||
}
|
||||
#endif
|
||||
|
|
236
special.cpp
236
special.cpp
|
@ -126,85 +126,71 @@ static QColor parseColorSpecification(QString colorSpec)
|
|||
|
||||
void dviWindow::color_special(QString cp)
|
||||
{
|
||||
// The color specials are ignored during the pre-scan phase, we use
|
||||
// them only during rendering
|
||||
if (PostScriptOutPutString == NULL) {
|
||||
|
||||
cp = cp.stripWhiteSpace();
|
||||
|
||||
QString command = KStringHandler::word(cp, (unsigned int)0);
|
||||
|
||||
if (command == "pop") {
|
||||
// Take color off the stack
|
||||
if (colorStack.isEmpty())
|
||||
printErrorMsgForSpecials( i18n("Error in DVIfile '%1', page %2. Color pop command issued when the color stack is empty." ).
|
||||
arg(dviFile->filename).arg(current_page));
|
||||
else
|
||||
colorStack.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (command == "push") {
|
||||
// Get color specification
|
||||
QColor col = parseColorSpecification(KStringHandler::word(cp, "1:"));
|
||||
// Set color
|
||||
if (col.isValid())
|
||||
colorStack.push(col);
|
||||
else
|
||||
colorStack.push(Qt::black);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get color specification and set the color for the rest of this
|
||||
// page
|
||||
QColor col = parseColorSpecification(cp);
|
||||
// Set color
|
||||
if (col.isValid())
|
||||
globalColor = col;
|
||||
cp = cp.stripWhiteSpace();
|
||||
|
||||
QString command = KStringHandler::word(cp, (unsigned int)0);
|
||||
|
||||
if (command == "pop") {
|
||||
// Take color off the stack
|
||||
if (colorStack.isEmpty())
|
||||
printErrorMsgForSpecials( i18n("Error in DVIfile '%1', page %2. Color pop command issued when the color stack is empty." ).
|
||||
arg(dviFile->filename).arg(current_page));
|
||||
else
|
||||
globalColor = Qt::black;
|
||||
colorStack.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (command == "push") {
|
||||
// Get color specification
|
||||
QColor col = parseColorSpecification(KStringHandler::word(cp, "1:"));
|
||||
// Set color
|
||||
if (col.isValid())
|
||||
colorStack.push(col);
|
||||
else
|
||||
colorStack.push(Qt::black);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get color specification and set the color for the rest of this
|
||||
// page
|
||||
QColor col = parseColorSpecification(cp);
|
||||
// Set color
|
||||
if (col.isValid())
|
||||
globalColor = col;
|
||||
else
|
||||
globalColor = Qt::black;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::background_special(QString cp)
|
||||
{
|
||||
// The color specials are ignored during rendering, and used only in
|
||||
// the pre-scan phase
|
||||
if (PostScriptOutPutString != NULL) {
|
||||
QColor col = parseColorSpecification(cp.stripWhiteSpace());
|
||||
if (col.isValid())
|
||||
PS_interface->setColor(current_page, col);
|
||||
return;
|
||||
}
|
||||
QColor col = parseColorSpecification(cp.stripWhiteSpace());
|
||||
if (col.isValid())
|
||||
PS_interface->setColor(current_page, col);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::html_anchor_special(QString cp)
|
||||
{
|
||||
if (PostScriptOutPutString != NULL) { // only during scanning, not during rendering
|
||||
cp.truncate(cp.find('"'));
|
||||
cp.truncate(cp.find('"'));
|
||||
#ifdef DEBUG_SPECIAL
|
||||
kdDebug(4300) << "HTML-special, anchor " << cp.latin1() << endl;
|
||||
kdDebug(4300) << "page " << current_page << endl;
|
||||
kdDebug(4300) << "HTML-special, anchor " << cp.latin1() << endl;
|
||||
kdDebug(4300) << "page " << current_page << endl;
|
||||
#endif
|
||||
|
||||
anchorList[cp] = DVI_Anchor(current_page, currinf.data.dvi_v);
|
||||
}
|
||||
anchorList[cp] = DVI_Anchor(current_page, currinf.data.dvi_v);
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::html_href_special(QString cp)
|
||||
{
|
||||
cp.truncate(cp.find('"'));
|
||||
|
||||
|
||||
#ifdef DEBUG_SPECIAL
|
||||
kdDebug(4300) << "HTML-special, href " << cp.latin1() << endl;
|
||||
#endif
|
||||
|
||||
if (!PostScriptOutPutString) { // only when rendering really takes place
|
||||
HTML_href = new QString(cp);
|
||||
}
|
||||
HTML_href = new QString(cp);
|
||||
}
|
||||
|
||||
void dviWindow::html_anchor_end(void)
|
||||
|
@ -225,9 +211,8 @@ void dviWindow::header_special(QString cp)
|
|||
kdDebug(4300) << "PostScript-special, header " << cp.latin1() << endl;
|
||||
#endif
|
||||
|
||||
if (PostScriptOutPutString && QFile::exists(cp)) {
|
||||
if (QFile::exists(cp))
|
||||
PS_interface->PostScriptHeaderString->append( QString(" (%1) run\n").arg(cp) );
|
||||
}
|
||||
}
|
||||
|
||||
void dviWindow::source_special(QString cp)
|
||||
|
@ -398,35 +383,34 @@ void dviWindow::epsf_special(QString cp)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::bang_special(QString cp)
|
||||
{
|
||||
#ifdef DEBUG_SPECIAL
|
||||
kdDebug(4300) << "PostScript-special, literal header " << cp.latin1() << endl;
|
||||
#endif
|
||||
|
||||
if (PostScriptOutPutString) {
|
||||
PS_interface->PostScriptHeaderString->append( " @defspecial \n" );
|
||||
PS_interface->PostScriptHeaderString->append( cp );
|
||||
PS_interface->PostScriptHeaderString->append( " @fedspecial \n" );
|
||||
}
|
||||
|
||||
PS_interface->PostScriptHeaderString->append( " @defspecial \n" );
|
||||
PS_interface->PostScriptHeaderString->append( cp );
|
||||
PS_interface->PostScriptHeaderString->append( " @fedspecial \n" );
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::quote_special(QString cp)
|
||||
{
|
||||
#ifdef DEBUG_SPECIAL
|
||||
kdError(4300) << "PostScript-special, literal PostScript " << cp.latin1() << endl;
|
||||
#endif
|
||||
|
||||
if (PostScriptOutPutString) {
|
||||
double PS_H = (currinf.data.dvi_h*300.0)/(65536*MFResolutions[font_pool->getMetafontMode()])-300;
|
||||
double PS_V = (currinf.data.dvi_v*300.0)/MFResolutions[font_pool->getMetafontMode()] - 300;
|
||||
PostScriptOutPutString->append( QString(" %1 %2 moveto\n").arg(PS_H).arg(PS_V) );
|
||||
PostScriptOutPutString->append( " @beginspecial @setspecial \n" );
|
||||
PostScriptOutPutString->append( cp );
|
||||
PostScriptOutPutString->append( " @endspecial \n" );
|
||||
}
|
||||
double PS_H = (currinf.data.dvi_h*300.0)/(65536*MFResolutions[font_pool->getMetafontMode()])-300;
|
||||
double PS_V = (currinf.data.dvi_v*300.0)/MFResolutions[font_pool->getMetafontMode()] - 300;
|
||||
PostScriptOutPutString->append( QString(" %1 %2 moveto\n").arg(PS_H).arg(PS_V) );
|
||||
PostScriptOutPutString->append( " @beginspecial @setspecial \n" );
|
||||
PostScriptOutPutString->append( cp );
|
||||
PostScriptOutPutString->append( " @endspecial \n" );
|
||||
}
|
||||
|
||||
|
||||
void dviWindow::ps_special(QString cp)
|
||||
{
|
||||
#ifdef DEBUG_SPECIAL
|
||||
|
@ -459,72 +443,90 @@ void dviWindow::applicationDoSpecial(char *cp)
|
|||
{
|
||||
QString special_command(cp);
|
||||
|
||||
// Encapsulated Postscript File
|
||||
if (special_command.find("src:", 0, false) == 0) {
|
||||
source_special(special_command.mid(4));
|
||||
// First come specials which is only interpreted during rendering,
|
||||
// and NOT during the prescan phase
|
||||
|
||||
// font color specials
|
||||
if (strncasecmp(cp, "color", 5) == 0) {
|
||||
if (PostScriptOutPutString == NULL)
|
||||
color_special(special_command.mid(5));
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML reference
|
||||
if (strncasecmp(cp, "html:<A href=", 13) == 0) {
|
||||
if (PostScriptOutPutString == NULL)
|
||||
html_href_special(special_command.mid(14));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Now to those specials which are only interpreted during the
|
||||
// prescan phase, and NOT during rendering.
|
||||
|
||||
// color special for background color
|
||||
if (strncasecmp(cp, "background", 10) == 0) {
|
||||
if (PostScriptOutPutString != NULL)
|
||||
background_special(special_command.mid(10));
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML anchor special
|
||||
if (strncasecmp(cp, "html:<A name=", 13) == 0) {
|
||||
if (PostScriptOutPutString != NULL)
|
||||
html_anchor_special(special_command.mid(14));
|
||||
return;
|
||||
}
|
||||
|
||||
// Postscript Header File
|
||||
if (strncasecmp(cp, "header=", 7) == 0) {
|
||||
if (PostScriptOutPutString != NULL)
|
||||
header_special(special_command.mid(7));
|
||||
return;
|
||||
}
|
||||
|
||||
// Literal Postscript Header
|
||||
if (cp[0] == '!') {
|
||||
if (PostScriptOutPutString != NULL)
|
||||
bang_special(special_command.mid(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Literal Postscript inclusion
|
||||
if (special_command[0] == '"') {
|
||||
quote_special(special_command.mid(1));
|
||||
if (cp[0] == '"') {
|
||||
if (PostScriptOutPutString != NULL)
|
||||
quote_special(special_command.mid(1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Finally there are those special commands which must be considered
|
||||
// both during rendering and during the pre-scan phase
|
||||
|
||||
// source special
|
||||
if (strncasecmp(cp, "src:", 4) == 0) {
|
||||
source_special(special_command.mid(4));
|
||||
return;
|
||||
}
|
||||
|
||||
// PS-Postscript inclusion
|
||||
if (special_command.find("ps:", 0, false) == 0) {
|
||||
if (strncasecmp(cp, "ps:", 3) == 0) {
|
||||
ps_special(special_command);
|
||||
return;
|
||||
}
|
||||
|
||||
// Literal Postscript Header
|
||||
if (special_command[0] == '!') {
|
||||
bang_special(special_command.mid(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Encapsulated Postscript File
|
||||
if (special_command.find("PSfile=", 0, false) == 0) {
|
||||
if (strncasecmp(cp, "PSfile=", 7) == 0) {
|
||||
epsf_special(special_command.mid(7));
|
||||
return;
|
||||
}
|
||||
|
||||
// Postscript Header File
|
||||
if (special_command.find("header=", 0, false) == 0) {
|
||||
header_special(special_command.mid(7));
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML reference
|
||||
if (special_command.find("html:<A href=", 0, false) == 0) {
|
||||
html_href_special(special_command.mid(14));
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML anchor end
|
||||
if (special_command.find("html:</A>", 0, false) == 0) {
|
||||
if (strncasecmp(cp, "html:</A>", 9) == 0) {
|
||||
html_anchor_end();
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML anchor special
|
||||
if (special_command.find("html:<A name=", 0, false) == 0) {
|
||||
html_anchor_special(special_command.mid(14));
|
||||
return;
|
||||
}
|
||||
|
||||
// color specials
|
||||
if (special_command.find("color", 0, false) == 0) {
|
||||
color_special(special_command.mid(5));
|
||||
return;
|
||||
}
|
||||
|
||||
// color special for background color
|
||||
if (special_command.find("background", 0, false) == 0) {
|
||||
background_special(special_command.mid(10));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
printErrorMsgForSpecials(i18n("The special command '%1' is not implemented.").arg(special_command));
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue