You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

714 lines
22 KiB

/*
* Copyright (c) 1994 Paul Vojta. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* NOTE:
* xdvi is based on prior work as noted in the modification history, below.
*/
/*
* DVI previewer for X.
*
* Eric Cooper, CMU, September 1985.
*
* Code derived from dvi-imagen.c.
*
* Modification history:
* 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
* 7/1988 Modified for X.11 --Mark Eichin, MIT
* 12/1988 Added 'R' option, toolkit, magnifying glass
* --Paul Vojta, UC Berkeley.
* 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
* 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
* 3/1990 Added VMS support --Scott Allendorf, U of Iowa
* 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
* 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
* and Lee Hetherington, MIT
* 4/1994 Added DPS support, bounding box
* --Ricardo Telichevesky
* and Luis Miguel Silveira, MIT RLE.
*/
#include <kdebug.h>
#include <klocale.h>
#include <qbitmap.h>
#include <qfile.h>
#include <qimage.h>
#include <qpainter.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fontpool.h"
#include "glyph.h"
#include "xdvi.h"
#include "TeXFontDefinition.h"
#include "TeXFont_PK.h"
//#define DEBUG_PK
#define PK_PRE 247
#define PK_ID 89
#define PK_MAGIC (PK_PRE << 8) + PK_ID
extern void oops(QString message);
TeXFont_PK::TeXFont_PK(TeXFontDefinition *parent)
: TeXFont(parent)
{
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::TeXFont_PK( parent=" << parent << ")" << endl;
#endif
for(unsigned int i=0; i<TeXFontDefinition::max_num_of_chars_in_font; i++)
characterBitmaps[i] = 0;
file = fopen(QFile::encodeName(parent->filename), "r");
if (file == 0)
kdError(4300) << i18n("Cannot open font file %1.").arg(parent->filename) << endl;
#ifdef DEBUG_PK
else
kdDebug(4300) << "TeXFont_PK::TeXFont_PK(): file opened successfully" << endl;
#endif
read_PK_index();
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::TeXFont_PK() ended" << endl;
#endif
}
TeXFont_PK::~TeXFont_PK()
{
//@@@ Release bitmaps
if (file != 0) {
fclose(file);
file = 0;
}
}
glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor color)
{
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )" << endl;
#endif
// Paranoia checks
if (ch >= TeXFontDefinition::max_num_of_chars_in_font) {
kdError(4300) << "TeXFont_PK::getGlyph(): Argument is too big." << endl;
return glyphtable;
}
// This is the address of the glyph that will be returned.
struct glyph *g = glyphtable+ch;
// Check if the glyph is loaded. If not, load it now.
if (characterBitmaps[ch] == 0) {
// If the character is not defined in the PK file, mark the
// character as missing, and print an error message
if (g->addr == 0) {
kdError(4300) << i18n("TexFont_PK::operator[]: Character %1 not defined in font %2").arg(ch).arg(parent->filename) << endl;
g->addr = -1;
return g;
}
// If the character has already been marked as missing, just
// return a pointer to the glyph (which will then be empty)
if (g->addr == -1)
return g;
// Otherwise, try to load the character
fseek(file, g->addr, 0);
read_PK_char(ch);
// Check if the character could be loaded. If not, mark the
// character as 'missing', and return a pointer.
if (characterBitmaps[ch]->bits == 0) {
g->addr = -1;
return g;
}
}
// At this point, g points to a properly loaded character. Generate
// a smoothly scaled QPixmap if the user asks for it.
if ((generateCharacterPixmap == true) &&
((g->shrunkenCharacter.isNull()) || (color != g->color)) &&
(characterBitmaps[ch]->w != 0)) {
g->color = color;
double shrinkFactor = MFResolutions[parent->font_pool->getMetafontMode()] / parent->displayResolution_in_dpi;
// All is fine? Then we rescale the bitmap in order to produce the
// required pixmap. Rescaling a character, however, is an art
// that requires some explanation...
//
// If we would just divide the size of the character and the
// coordinates by the shrink factor, then the result would look
// quite ugly: due to the ineviatable rounding errors in the
// integer arithmetic, the characters would be displaced by up to
// 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);
// Generate the alpha-channel. This again is highly inefficient.
// Would anybody please produce a faster routine?
QImage im32(shrunk_width, shrunk_height, 32);
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];
}
}
g->shrunkenCharacter.convertFromImage(im32,0);
g->shrunkenCharacter.setOptimization(QPixmap::BestOptim);
}
return g;
}
#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))
// This table is used for changing the bit order in a byte. The
// expression bitflp[byte] takes a byte in big endian and gives the
// little endian equivalent of that.
static const uchar bitflip[256] = {
0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
};
static BMUNIT bit_masks[33] = {
0x0, 0x1, 0x3, 0x7,
0xf, 0x1f, 0x3f, 0x7f,
0xff, 0x1ff, 0x3ff, 0x7ff,
0xfff, 0x1fff, 0x3fff, 0x7fff,
0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
0xffffffff
};
#define PK_ID 89
#define PK_CMD_START 240
#define PK_X1 240
#define PK_X2 241
#define PK_X3 242
#define PK_X4 243
#define PK_Y 244
#define PK_POST 245
#define PK_NOOP 246
#define PK_PRE 247
int TeXFont_PK::PK_get_nyb(FILE *fp)
{
#ifdef DEBUG_PK
kdDebug(4300) << "PK_get_nyb" << endl;
#endif
unsigned temp;
if (PK_bitpos < 0) {
PK_input_byte = one(fp);
PK_bitpos = 4;
}
temp = PK_input_byte >> PK_bitpos;
PK_bitpos -= 4;
return (temp & 0xf);
}
int TeXFont_PK::PK_packed_num(FILE *fp)
{
#ifdef DEBUG_PK
kdDebug(4300) << "PK_packed_num" << endl;
#endif
int i,j;
if ((i = PK_get_nyb(fp)) == 0) {
do {
j = PK_get_nyb(fp);
++i;
}
while (j == 0);
while (i > 0) {
j = (j << 4) | PK_get_nyb(fp);
--i;
}
return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
}
else {
if (i <= PK_dyn_f) return i;
if (i < 14)
return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
+ PK_dyn_f + 1);
if (i == 14) PK_repeat_count = PK_packed_num(fp);
else PK_repeat_count = 1;
return PK_packed_num(fp);
}
}
void TeXFont_PK::PK_skip_specials(void)
{
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::PK_skip_specials() called" << endl;
#endif
int i,j;
register FILE *fp = file;
#ifdef DEBUG_PK
if (fp == 0)
kdDebug(4300) << "TeXFont_PK::PK_skip_specials(): file == 0" << endl;
#endif
do {
PK_flag_byte = one(fp);
if (PK_flag_byte >= PK_CMD_START) {
switch (PK_flag_byte) {
case PK_X1 :
case PK_X2 :
case PK_X3 :
case PK_X4 :
i = 0;
for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
i = (i << 8) | one(fp);
while (i--) (void) one(fp);
break;
case PK_Y :
(void) four(fp);
case PK_POST :
case PK_NOOP :
break;
default :
oops(i18n("Unexpected %1 in PK file %2").arg(PK_flag_byte).arg(parent->filename) );
break;
}
}
}
while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::PK_skip_specials() ended" << endl;
#endif
}
void TeXFont_PK::read_PK_char(unsigned int ch)
{
#ifdef DEBUG_PK
kdDebug(4300) << "read_PK_char" << endl;
#endif
int i, j;
int n;
int row_bit_pos;
bool paint_switch;
BMUNIT *cp;
register struct glyph *g;
register FILE *fp = file;
long fpwidth;
BMUNIT word = 0;
int word_weight, bytes_wide;
int rows_left, h_bit, count;
g = glyphtable + ch;
PK_flag_byte = g->x2;
PK_dyn_f = PK_flag_byte >> 4;
paint_switch = ((PK_flag_byte & 8) != 0);
PK_flag_byte &= 0x7;
if (PK_flag_byte == 7)
n = 4;
else
if (PK_flag_byte > 3)
n = 2;
else
n = 1;
#ifdef DEBUG_PK
kdDebug(4300) << "loading pk char " << ch << ", char type " << n << endl;
#endif
if (characterBitmaps[ch] == 0)
characterBitmaps[ch] = new bitmap();
/*
* now read rest of character preamble
*/
if (n != 4)
fpwidth = num(fp, 3);
else {
fpwidth = sfour(fp);
(void) four(fp); /* horizontal escapement */
}
(void) num(fp, n); /* vertical escapement */
{
unsigned long w, h;
w = num(fp, n);
h = num(fp, n);
if (w > 0x7fff || h > 0x7fff)
oops(i18n("The character %1 is too large in file %2").arg(ch).arg(parent->filename));
characterBitmaps[ch]->w = w;
characterBitmaps[ch]->h = h;
}
g->x = snum(fp, n);
g->y = snum(fp, n);
g->dvi_advance_in_units_of_design_size_by_2e20 = fpwidth;
{
/* 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;
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;
/*
* read character data into *cp
*/
bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
PK_bitpos = -1;
// The routines which read the character depend on the byte
// ordering. In principle, the byte 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
// at runtime. That should of course be changed in the future.
int wordSize;
bool bigEndian;
qSysInfo (&wordSize, &bigEndian);
if (bigEndian) {
// Routine for big Endian machines. Applies e.g. to Motorola and
// (Ultra-)Sparc processors.
#ifdef DEBUG_PK
kdDebug(4300) << "big Endian byte ordering" << endl;
#endif
if (PK_dyn_f == 14) { /* get raster by bits */
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;
for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
if (--PK_bitpos < 0) {
word = one(fp);
PK_bitpos = 7;
}
if (--row_bit_pos < 0) {
cp++;
row_bit_pos = BITS_PER_BMUNIT - 1;
}
if (word & (1 << PK_bitpos))
*cp |= 1 << row_bit_pos;
}
}
} else { /* get packed raster */
rows_left = characterBitmaps[ch]->h;
h_bit = characterBitmaps[ch]->w;
PK_repeat_count = 0;
word_weight = BITS_PER_BMUNIT;
word = 0;
while (rows_left > 0) {
count = PK_packed_num(fp);
while (count > 0) {
if (count < word_weight && count < h_bit) {
h_bit -= count;
word_weight -= count;
if (paint_switch)
word |= bit_masks[count] << word_weight;
count = 0;
} else
if (count >= h_bit && h_bit <= word_weight) {
if (paint_switch)
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) {
*cp = *SUB(cp, bytes_wide);
++cp;
}
rows_left -= PK_repeat_count + 1;
PK_repeat_count = 0;
word = 0;
word_weight = BITS_PER_BMUNIT;
count -= h_bit;
h_bit = characterBitmaps[ch]->w;
} else {
if (paint_switch)
word |= bit_masks[word_weight];
*cp++ = word;
word = 0;
count -= word_weight;
h_bit -= word_weight;
word_weight = BITS_PER_BMUNIT;
}
}
paint_switch = 1 - paint_switch;
}
if (cp != ((BMUNIT *) (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.
register unsigned char* bitmapData = (unsigned char*) characterBitmaps[ch]->bits;
register unsigned char* endOfData = bitmapData + characterBitmaps[ch]->bytes_wide*characterBitmaps[ch]->h;
while(bitmapData < endOfData) {
*bitmapData = bitflip[*bitmapData];
bitmapData++;
}
} else {
// Routines for small Endian start here. This applies e.g. to
// Intel and Alpha processors.
#ifdef DEBUG_PK
kdDebug(4300) << "small Endian byte ordering" << endl;
#endif
if (PK_dyn_f == 14) { /* get raster by bits */
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 = -1;
for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
if (--PK_bitpos < 0) {
word = one(fp);
PK_bitpos = 7;
}
if (++row_bit_pos >= BITS_PER_BMUNIT) {
cp++;
row_bit_pos = 0;
}
if (word & (1 << PK_bitpos))
*cp |= 1 << row_bit_pos;
}
}
} else { /* get packed raster */
rows_left = characterBitmaps[ch]->h;
h_bit = characterBitmaps[ch]->w;
PK_repeat_count = 0;
word_weight = BITS_PER_BMUNIT;
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);
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);
*cp++ = word;
/* "output" row(s) */
for (i = PK_repeat_count * bytes_wide /
BYTES_PER_BMUNIT; 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;
count -= h_bit;
h_bit = characterBitmaps[ch]->w;
} else {
if (paint_switch)
word |= bit_masks[word_weight] << (BITS_PER_BMUNIT - word_weight);
*cp++ = word;
word = 0;
count -= word_weight;
h_bit -= word_weight;
word_weight = BITS_PER_BMUNIT;
}
}
paint_switch = 1 - paint_switch;
}
if (cp != ((BMUNIT *) (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));
}
} // endif: big or small Endian?
}
void TeXFont_PK::read_PK_index(void)
{
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::read_PK_index() called" << endl;
#endif
if (file == 0) {
kdError(4300) << "TeXFont_PK::read_PK_index(): file == 0" << endl;
return;
}
int magic = two(file);
if (magic != PK_MAGIC) {
kdError(4300) << "TeXFont_PK::read_PK_index(): file is not a PK file" << endl;
return;
}
fseek(file, (long) one(file), SEEK_CUR); /* skip comment */
(void) four(file); /* skip design size */
checksum = four(file);
int hppp = sfour(file);
int vppp = sfour(file);
if (hppp != vppp)
kdWarning(4300) << i18n("Font has non-square aspect ratio ") << vppp << ":" << hppp << endl;
// Read glyph directory (really a whole pass over the file).
for (;;) {
int bytes_left, flag_low_bits;
unsigned int ch;
PK_skip_specials();
if (PK_flag_byte == PK_POST)
break;
flag_low_bits = PK_flag_byte & 0x7;
if (flag_low_bits == 7) {
bytes_left = four(file);
ch = four(file);
} else
if (flag_low_bits > 3) {
bytes_left = ((flag_low_bits - 4) << 16) + two(file);
ch = one(file);
} else {
bytes_left = (flag_low_bits << 8) + one(file);
ch = one(file);
}
glyphtable[ch].addr = ftell(file);
glyphtable[ch].x2 = PK_flag_byte;
fseek(file, (long) bytes_left, SEEK_CUR);
#ifdef DEBUG_PK
kdDebug(4300) << "Scanning pk char " << ch << "at " << glyphtable[ch].addr << endl;
#endif
}
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::read_PK_index() called" << endl;
#endif
}