1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
3 * Copyright (c) 1994 Paul Vojta. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * xdvi is based on prior work as noted in the modification history, below.
31 * DVI previewer for X.
33 * Eric Cooper, CMU, September 1985.
35 * Code derived from dvi-imagen.c.
37 * Modification history:
38 * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
39 * 7/1988 Modified for X.11 --Mark Eichin, MIT
40 * 12/1988 Added 'R' option, toolkit, magnifying glass
41 * --Paul Vojta, UC Berkeley.
42 * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
43 * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
44 * 3/1990 Added VMS support --Scott Allendorf, U of Iowa
45 * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
46 * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
47 * and Lee Hetherington, MIT
48 * 4/1994 Added DPS support, bounding box
49 * --Ricardo Telichevesky
50 * and Luis Miguel Silveira, MIT RLE.
55 #include "TeXFont_PK.h"
57 #include "kvs_debug.h"
72 #define PK_MAGIC (PK_PRE << 8) + PK_ID
75 extern void oops(const QString
& message
);
79 TeXFont_PK::TeXFont_PK(TeXFontDefinition
*parent
)
83 kDebug(kvs::dvi
) << "TeXFont_PK::TeXFont_PK( parent=" << parent
<< ")";
86 for(unsigned int i
=0; i
<TeXFontDefinition::max_num_of_chars_in_font
; i
++)
87 characterBitmaps
[i
] = 0;
88 file
= fopen(QFile::encodeName(parent
->filename
), "r");
90 kError(kvs::dvi
) << i18n("Cannot open font file %1.", parent
->filename
) << endl
;
93 kDebug(kvs::dvi
) << "TeXFont_PK::TeXFont_PK(): file opened successfully";
99 kDebug(kvs::dvi
) << "TeXFont_PK::TeXFont_PK() ended";
104 TeXFont_PK::~TeXFont_PK()
106 //@@@ Release bitmaps
115 glyph
* TeXFont_PK::getGlyph(quint16 ch
, bool generateCharacterPixmap
, const QColor
& color
)
118 kDebug(kvs::dvi
) << "TeXFont_PK::getGlyph( ch=" << ch
<< ", generateCharacterPixmap=" << generateCharacterPixmap
<< " )";
122 if (ch
>= TeXFontDefinition::max_num_of_chars_in_font
) {
123 kError(kvs::dvi
) << "TeXFont_PK::getGlyph(): Argument is too big." << endl
;
127 // This is the address of the glyph that will be returned.
128 class glyph
*g
= glyphtable
+ch
;
130 // Check if the glyph is loaded. If not, load it now.
131 if (characterBitmaps
[ch
] == 0) {
132 // If the character is not defined in the PK file, mark the
133 // character as missing, and print an error message
135 kError(kvs::dvi
) << i18n("TexFont_PK::operator[]: Character %1 not defined in font %2", ch
, parent
->filename
) << endl
;
140 // If the character has already been marked as missing, just
141 // return a pointer to the glyph (which will then be empty)
145 // Otherwise, try to load the character
146 fseek(file
, g
->addr
, 0);
148 // Check if the character could be loaded. If not, mark the
149 // character as 'missing', and return a pointer.
150 if (characterBitmaps
[ch
]->bits
== 0) {
156 // At this point, g points to a properly loaded character. Generate
157 // a smoothly scaled QPixmap if the user asks for it.
158 if ((generateCharacterPixmap
== true) &&
159 ((g
->shrunkenCharacter
.isNull()) || (color
!= g
->color
)) &&
160 (characterBitmaps
[ch
]->w
!= 0)) {
162 double shrinkFactor
= 1200 / parent
->displayResolution_in_dpi
;
164 // All is fine? Then we rescale the bitmap in order to produce the
165 // required pixmap. Rescaling a character, however, is an art
166 // that requires some explanation...
168 // If we would just divide the size of the character and the
169 // coordinates by the shrink factor, then the result would look
170 // quite ugly: due to the ineviatable rounding errors in the
171 // integer arithmetic, the characters would be displaced by up to
172 // a pixel. That doesn't sound much, but on low-resolution
173 // devices, such as a notebook screen, the effect would be a
174 // "dancing line" of characters, which looks really bad.
176 // Calculate the coordinates of the hot point in the shrunken
177 // bitmap. For simplicity, let us consider the x-coordinate
178 // first. In principle, the hot point should have an x-coordinate
179 // of (g->x/shrinkFactor). That, however, will generally NOT be an
180 // integral number. The cure is to translate the source image
181 // somewhat, so that the x-coordinate of the hot point falls onto
182 // the round-up of this number, i.e.
183 g
->x2
= (int)ceil(g
->x
/shrinkFactor
);
185 // Translating and scaling then means that the pixel in the scaled
186 // image which covers the range [x,x+1) corresponds to the range
187 // [x*shrinkFactor+srcXTrans, (x+1)*shrinkFactor+srcXTrans), where
188 // srcXTrans is the following NEGATIVE number
189 double srcXTrans
= shrinkFactor
* (g
->x
/shrinkFactor
- ceil(g
->x
/shrinkFactor
));
191 // How big will the shrunken bitmap then become? If shrunk_width
192 // denotes that width of the scaled image, and
193 // characterBitmaps[ch]->w the width of the orininal image, we
194 // need to make sure that the following inequality holds:
196 // shrunk_width*shrinkFactor+srcXTrans >= characterBitmaps[ch]->w
199 int shrunk_width
= (int)ceil( (characterBitmaps
[ch
]->w
- srcXTrans
)/shrinkFactor
);
201 // Now do the same for the y-coordinate
202 g
->y2
= (int)ceil(g
->y
/shrinkFactor
);
203 double srcYTrans
= shrinkFactor
* (g
->y
/shrinkFactor
- ceil(g
->y
/shrinkFactor
));
204 int shrunk_height
= (int)ceil( (characterBitmaps
[ch
]->h
- srcYTrans
)/shrinkFactor
);
206 // Turn the image into 8 bit
207 QByteArray
translated(characterBitmaps
[ch
]->w
* characterBitmaps
[ch
]->h
, '\0');
208 quint8
*data
= (quint8
*)translated
.data();
209 for(int x
=0; x
<characterBitmaps
[ch
]->w
; x
++)
210 for(int y
=0; y
<characterBitmaps
[ch
]->h
; y
++) {
211 quint8 bit
= *(characterBitmaps
[ch
]->bits
+ characterBitmaps
[ch
]->bytes_wide
*y
+ (x
>> 3));
212 bit
= bit
>> (x
& 7);
214 data
[characterBitmaps
[ch
]->w
*y
+ x
] = bit
;
217 // Now shrink the image. We shrink the X-direction first
218 QByteArray
xshrunk(shrunk_width
*characterBitmaps
[ch
]->h
, '\0');
219 quint8
*xdata
= (quint8
*)xshrunk
.data();
221 // Do the shrinking. The pixel (x,y) that we want to calculate
222 // corresponds to the line segment from
224 // [shrinkFactor*x+srcXTrans, shrinkFactor*(x+1)+srcXTrans)
226 // The trouble is, these numbers are in general no integers.
228 for(int y
=0; y
<characterBitmaps
[ch
]->h
; y
++)
229 for(int x
=0; x
<shrunk_width
; x
++) {
231 double destStartX
= shrinkFactor
*x
+srcXTrans
;
232 double destEndX
= shrinkFactor
*(x
+1)+srcXTrans
;
233 for(int srcX
=(int)ceil(destStartX
); srcX
<floor(destEndX
); srcX
++)
234 if ((srcX
>= 0) && (srcX
< characterBitmaps
[ch
]->w
))
235 value
+= data
[characterBitmaps
[ch
]->w
*y
+ srcX
] * 255;
237 if (destStartX
>= 0.0)
238 value
+= (quint32
) (255.0*(ceil(destStartX
)-destStartX
) * data
[characterBitmaps
[ch
]->w
*y
+ (int)floor(destStartX
)]);
239 if (floor(destEndX
) < characterBitmaps
[ch
]->w
)
240 value
+= (quint32
) (255.0*(destEndX
-floor(destEndX
)) * data
[characterBitmaps
[ch
]->w
*y
+ (int)floor(destEndX
)]);
242 xdata
[shrunk_width
*y
+ x
] = (int)(value
/shrinkFactor
+ 0.5);
245 // Now shrink the Y-direction
246 QByteArray
xyshrunk(shrunk_width
*shrunk_height
, '\0');
247 quint8
*xydata
= (quint8
*)xyshrunk
.data();
248 for(int x
=0; x
<shrunk_width
; x
++)
249 for(int y
=0; y
<shrunk_height
; y
++) {
251 double destStartY
= shrinkFactor
*y
+srcYTrans
;
252 double destEndY
= shrinkFactor
*(y
+1)+srcYTrans
;
253 for(int srcY
=(int)ceil(destStartY
); srcY
<floor(destEndY
); srcY
++)
254 if ((srcY
>= 0) && (srcY
< characterBitmaps
[ch
]->h
))
255 value
+= xdata
[shrunk_width
*srcY
+ x
];
257 if (destStartY
>= 0.0)
258 value
+= (quint32
) ((ceil(destStartY
)-destStartY
) * xdata
[shrunk_width
*(int)floor(destStartY
) + x
]);
259 if (floor(destEndY
) < characterBitmaps
[ch
]->h
)
260 value
+= (quint32
) ((destEndY
-floor(destEndY
)) * xdata
[shrunk_width
*(int)floor(destEndY
) + x
]);
262 xydata
[shrunk_width
*y
+ x
] = (int)(value
/shrinkFactor
);
265 QImage
im32(shrunk_width
, shrunk_height
, QImage::Format_ARGB32
);
266 // Do QPixmaps fully support the alpha channel? If yes, we use
267 // that. Otherwise, use other routines as a fallback
268 if (parent
->font_pool
->QPixmapSupportsAlpha
) {
269 // If the alpha channel is properly supported, we set the
270 // character glyph to a colored rectangle, and define the
271 // character outline only using the alpha channel. That ensures
272 // good quality rendering for overlapping characters.
273 im32
.fill(qRgb(color
.red(), color
.green(), color
.blue()));
274 for(quint16 y
=0; y
<shrunk_height
; y
++) {
275 quint8
*destScanLine
= (quint8
*)im32
.scanLine(y
);
276 for(quint16 col
=0; col
<shrunk_width
; col
++)
277 destScanLine
[4*col
+3] = xydata
[shrunk_width
*y
+ col
];
280 // If the alpha channel is not supported... QT seems to turn the
281 // alpha channel into a crude bitmap which is used to mask the
282 // resulting QPixmap. In this case, we define the character
283 // outline using the image data, and use the alpha channel only
284 // to store "maximally opaque" or "completely transparent"
285 // values. When characters are rendered, overlapping characters
286 // are no longer correctly drawn, but quality is still
287 // sufficient for most purposes. One notable exception is output
288 // from the gftodvi program, which will be partially unreadable.
289 quint16 rInv
= 0xFF - color
.red();
290 quint16 gInv
= 0xFF - color
.green();
291 quint16 bInv
= 0xFF - color
.blue();
293 quint8
*srcScanLine
= xydata
;
294 for(quint16 y
=0; y
<shrunk_height
; y
++) {
295 unsigned int *destScanLine
= (unsigned int *)im32
.scanLine(y
);
296 for(quint16 col
=0; col
<shrunk_width
; col
++) {
297 quint16 data
= *srcScanLine
;
298 // The value stored in "data" now has the following meaning:
299 // data = 0 -> white; data = 0xff -> use "color"
300 *destScanLine
= qRgba(0xFF - (rInv
*data
+ 0x7F) / 0xFF,
301 0xFF - (gInv
*data
+ 0x7F) / 0xFF,
302 0xFF - (bInv
*data
+ 0x7F) / 0xFF,
303 (data
> 0x03) ? 0xff : 0x00);
310 g
->shrunkenCharacter
= im32
;
317 #define ADD(a, b) ((quint32 *) (((char *) a) + b))
318 #define SUB(a, b) ((quint32 *) (((char *) a) - b))
322 // This table is used for changing the bit order in a byte. The
323 // expression bitflp[byte] takes a byte in big endian and gives the
324 // little endian equivalent of that.
325 static const uchar bitflip
[256] = {
326 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
327 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
328 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
329 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
330 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
331 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
332 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
333 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
334 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
335 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
336 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
337 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
338 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
339 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
340 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
341 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
344 static quint32 bit_masks
[33] = {
346 0xf, 0x1f, 0x3f, 0x7f,
347 0xff, 0x1ff, 0x3ff, 0x7ff,
348 0xfff, 0x1fff, 0x3fff, 0x7fff,
349 0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
350 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
351 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
352 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
358 #define PK_CMD_START 240
369 int TeXFont_PK::PK_get_nyb(FILE *fp
)
372 kDebug(kvs::dvi
) << "PK_get_nyb";
377 PK_input_byte
= one(fp
);
380 temp
= PK_input_byte
>> PK_bitpos
;
386 int TeXFont_PK::PK_packed_num(FILE *fp
)
389 kDebug(kvs::dvi
) << "PK_packed_num";
394 if ((i
= PK_get_nyb(fp
)) == 0) {
401 j
= (j
<< 4) | PK_get_nyb(fp
);
404 return (j
- 15 + ((13 - PK_dyn_f
) << 4) + PK_dyn_f
);
407 if (i
<= PK_dyn_f
) return i
;
409 return (((i
- PK_dyn_f
- 1) << 4) + PK_get_nyb(fp
)
411 if (i
== 14) PK_repeat_count
= PK_packed_num(fp
);
412 else PK_repeat_count
= 1;
413 return PK_packed_num(fp
);
418 void TeXFont_PK::PK_skip_specials()
421 kDebug(kvs::dvi
) << "TeXFont_PK::PK_skip_specials() called";
425 register FILE *fp
= file
;
429 kDebug(kvs::dvi
) << "TeXFont_PK::PK_skip_specials(): file == 0";
433 PK_flag_byte
= one(fp
);
434 if (PK_flag_byte
>= PK_CMD_START
) {
435 switch (PK_flag_byte
) {
441 for (j
= PK_CMD_START
; j
<= PK_flag_byte
; ++j
)
442 i
= (i
<< 8) | one(fp
);
443 while (i
--) (void) one(fp
);
451 oops(i18n("Unexpected %1 in PK file %2", PK_flag_byte
, parent
->filename
) );
456 while (PK_flag_byte
!= PK_POST
&& PK_flag_byte
>= PK_CMD_START
);
459 kDebug(kvs::dvi
) << "TeXFont_PK::PK_skip_specials() ended";
464 void TeXFont_PK::read_PK_char(unsigned int ch
)
467 kDebug(kvs::dvi
) << "read_PK_char";
475 register class glyph
*g
;
476 register FILE *fp
= file
;
479 int word_weight
, bytes_wide
;
480 int rows_left
, h_bit
, count
;
483 PK_flag_byte
= g
->x2
;
484 PK_dyn_f
= PK_flag_byte
>> 4;
485 paint_switch
= ((PK_flag_byte
& 8) != 0);
487 if (PK_flag_byte
== 7)
490 if (PK_flag_byte
> 3)
496 kDebug(kvs::dvi
) << "loading pk char " << ch
<< ", char type " << n
;
499 if (characterBitmaps
[ch
] == 0)
500 characterBitmaps
[ch
] = new bitmap();
503 * now read rest of character preamble
506 fpwidth
= num(fp
, 3);
509 (void) four(fp
); /* horizontal escapement */
511 (void) num(fp
, n
); /* vertical escapement */
517 if (w
> 0x7fff || h
> 0x7fff)
518 oops(i18n("The character %1 is too large in file %2", ch
, parent
->filename
));
519 characterBitmaps
[ch
]->w
= w
;
520 characterBitmaps
[ch
]->h
= h
;
525 g
->dvi_advance_in_units_of_design_size_by_2e20
= fpwidth
;
528 /* width must be multiple of 16 bits for raster_op */
529 characterBitmaps
[ch
]->bytes_wide
= ROUNDUP((int) characterBitmaps
[ch
]->w
, 32) * 4;
530 register unsigned int size
= characterBitmaps
[ch
]->bytes_wide
* characterBitmaps
[ch
]->h
;
531 characterBitmaps
[ch
]->bits
= new char[size
!= 0 ? size
: 1];
534 cp
= (quint32
*) characterBitmaps
[ch
]->bits
;
537 * read character data into *cp
539 bytes_wide
= ROUNDUP((int) characterBitmaps
[ch
]->w
, 32) * 4;
542 // The routines which read the character depend on the bit
543 // ordering. In principle, the bit order should be detected at
544 // compile time and the proper routing chosen. For the moment, as
545 // autoconf is somewhat complicated for the author, we prefer a
546 // simpler -even if somewhat slower approach and detect the ordering
547 // at runtime. That should of course be changed in the future.
549 if (QSysInfo::ByteOrder
== QSysInfo::BigEndian
) {
550 // Routine for big Endian machines. Applies e.g. to Motorola and
551 // (Ultra-)Sparc processors.
554 kDebug(kvs::dvi
) << "big Endian byte ordering";
557 if (PK_dyn_f
== 14) { /* get raster by bits */
558 memset(characterBitmaps
[ch
]->bits
, 0, (int) characterBitmaps
[ch
]->h
* bytes_wide
);
559 for (i
= 0; i
< (int) characterBitmaps
[ch
]->h
; i
++) { /* get all rows */
560 cp
= ADD(characterBitmaps
[ch
]->bits
, i
* bytes_wide
);
562 for (j
= 0; j
< (int) characterBitmaps
[ch
]->w
; j
++) { /* get one row */
563 if (--PK_bitpos
< 0) {
567 if (--row_bit_pos
< 0) {
569 row_bit_pos
= 32 - 1;
571 if (word
& (1 << PK_bitpos
))
572 *cp
|= 1 << row_bit_pos
;
575 } else { /* get packed raster */
576 rows_left
= characterBitmaps
[ch
]->h
;
577 h_bit
= characterBitmaps
[ch
]->w
;
581 while (rows_left
> 0) {
582 count
= PK_packed_num(fp
);
584 if (count
< word_weight
&& count
< h_bit
) {
586 word_weight
-= count
;
588 word
|= bit_masks
[count
] << word_weight
;
591 if (count
>= h_bit
&& h_bit
<= word_weight
) {
593 word
|= bit_masks
[h_bit
] << (word_weight
- h_bit
);
595 /* "output" row(s) */
596 for (i
= PK_repeat_count
* bytes_wide
/ 4; i
> 0; --i
) {
597 *cp
= *SUB(cp
, bytes_wide
);
600 rows_left
-= PK_repeat_count
+ 1;
605 h_bit
= characterBitmaps
[ch
]->w
;
608 word
|= bit_masks
[word_weight
];
611 count
-= word_weight
;
612 h_bit
-= word_weight
;
616 paint_switch
= 1 - paint_switch
;
618 if (cp
!= ((quint32
*) (characterBitmaps
[ch
]->bits
+ bytes_wide
* characterBitmaps
[ch
]->h
)))
619 oops(i18n("Wrong number of bits stored: char. %1, font %2", ch
, parent
->filename
));
620 if (rows_left
!= 0 || h_bit
!= characterBitmaps
[ch
]->w
)
621 oops(i18n("Bad pk file (%1), too many bits", parent
->filename
));
624 // The data in the bitmap is now in the processor's bit order,
625 // that is, big endian. Since XWindows needs little endian, we
626 // need to change the bit order now.
627 register unsigned char* bitmapData
= (unsigned char*) characterBitmaps
[ch
]->bits
;
628 register unsigned char* endOfData
= bitmapData
+ characterBitmaps
[ch
]->bytes_wide
*characterBitmaps
[ch
]->h
;
629 while(bitmapData
< endOfData
) {
630 *bitmapData
= bitflip
[*bitmapData
];
636 // Routines for small Endian start here. This applies e.g. to
637 // Intel and Alpha processors.
640 kDebug(kvs::dvi
) << "small Endian byte ordering";
643 if (PK_dyn_f
== 14) { /* get raster by bits */
644 memset(characterBitmaps
[ch
]->bits
, 0, (int) characterBitmaps
[ch
]->h
* bytes_wide
);
645 for (i
= 0; i
< (int) characterBitmaps
[ch
]->h
; i
++) { /* get all rows */
646 cp
= ADD(characterBitmaps
[ch
]->bits
, i
* bytes_wide
);
648 for (j
= 0; j
< (int) characterBitmaps
[ch
]->w
; j
++) { /* get one row */
649 if (--PK_bitpos
< 0) {
653 if (++row_bit_pos
>= 32) {
657 if (word
& (1 << PK_bitpos
))
658 *cp
|= 1 << row_bit_pos
;
661 } else { /* get packed raster */
662 rows_left
= characterBitmaps
[ch
]->h
;
663 h_bit
= characterBitmaps
[ch
]->w
;
667 while (rows_left
> 0) {
668 count
= PK_packed_num(fp
);
670 if (count
< word_weight
&& count
< h_bit
) {
672 word
|= bit_masks
[count
] << (32 - word_weight
);
674 word_weight
-= count
;
677 if (count
>= h_bit
&& h_bit
<= word_weight
) {
679 word
|= bit_masks
[h_bit
] << (32 - word_weight
);
681 /* "output" row(s) */
682 for (i
= PK_repeat_count
* bytes_wide
/ 4; i
> 0; --i
) {
683 *cp
= *SUB(cp
, bytes_wide
);
686 rows_left
-= PK_repeat_count
+ 1;
691 h_bit
= characterBitmaps
[ch
]->w
;
694 word
|= bit_masks
[word_weight
] << (32 - word_weight
);
697 count
-= word_weight
;
698 h_bit
-= word_weight
;
702 paint_switch
= 1 - paint_switch
;
704 if (cp
!= ((quint32
*) (characterBitmaps
[ch
]->bits
+ bytes_wide
* characterBitmaps
[ch
]->h
)))
705 oops(i18n("Wrong number of bits stored: char. %1, font %2", ch
, parent
->filename
));
706 if (rows_left
!= 0 || h_bit
!= characterBitmaps
[ch
]->w
)
707 oops(i18n("Bad pk file (%1), too many bits", parent
->filename
));
709 } // endif: big or small Endian?
713 void TeXFont_PK::read_PK_index()
716 kDebug(kvs::dvi
) << "TeXFont_PK::read_PK_index() called";
720 kError(kvs::dvi
) << "TeXFont_PK::read_PK_index(): file == 0" << endl
;
724 int magic
= two(file
);
725 if (magic
!= PK_MAGIC
) {
726 kError(kvs::dvi
) << "TeXFont_PK::read_PK_index(): file is not a PK file" << endl
;
730 fseek(file
, (long) one(file
), SEEK_CUR
); /* skip comment */
731 (void) four(file
); /* skip design size */
733 checksum
= four(file
);
735 int hppp
= sfour(file
);
736 int vppp
= sfour(file
);
738 kWarning(kvs::dvi
) << i18n("Font has non-square aspect ratio ") << vppp
<< ":" << hppp
;
740 // Read glyph directory (really a whole pass over the file).
742 int bytes_left
, flag_low_bits
;
746 if (PK_flag_byte
== PK_POST
)
748 flag_low_bits
= PK_flag_byte
& 0x7;
749 if (flag_low_bits
== 7) {
750 bytes_left
= four(file
);
753 if (flag_low_bits
> 3) {
754 bytes_left
= ((flag_low_bits
- 4) << 16) + two(file
);
757 bytes_left
= (flag_low_bits
<< 8) + one(file
);
761 glyphtable
[ch
].addr
= ftell(file
);
762 glyphtable
[ch
].x2
= PK_flag_byte
;
763 fseek(file
, (long) bytes_left
, SEEK_CUR
);
765 kDebug(kvs::dvi
) << "Scanning pk char " << ch
<< "at " << glyphtable
[ch
].addr
;
769 kDebug(kvs::dvi
) << "TeXFont_PK::read_PK_index() called";