SVN_SILENT made messages (.desktop file)
[kdegraphics.git] / okular / generators / dvi / TeXFont_PK.cpp
blob1477eb3154b9985b6750e6070c2558c096154d7a
1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
2 /*
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
7 * are met:
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
24 * SUCH DAMAGE.
26 * NOTE:
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.
53 #include <config.h>
55 #include "TeXFont_PK.h"
56 #include "fontpool.h"
57 #include "kvs_debug.h"
58 #include "xdvi.h"
60 #include <klocale.h>
62 #include <QFile>
63 #include <QImage>
65 #include <cmath>
66 #include <math.h>
68 //#define DEBUG_PK
70 #define PK_PRE 247
71 #define PK_ID 89
72 #define PK_MAGIC (PK_PRE << 8) + PK_ID
75 extern void oops(const QString& message);
79 TeXFont_PK::TeXFont_PK(TeXFontDefinition *parent)
80 : TeXFont(parent)
82 #ifdef DEBUG_PK
83 kDebug(kvs::dvi) << "TeXFont_PK::TeXFont_PK( parent=" << parent << ")";
84 #endif
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");
89 if (file == 0)
90 kError(kvs::dvi) << i18n("Cannot open font file %1.", parent->filename) << endl;
91 #ifdef DEBUG_PK
92 else
93 kDebug(kvs::dvi) << "TeXFont_PK::TeXFont_PK(): file opened successfully";
94 #endif
96 read_PK_index();
98 #ifdef DEBUG_PK
99 kDebug(kvs::dvi) << "TeXFont_PK::TeXFont_PK() ended";
100 #endif
104 TeXFont_PK::~TeXFont_PK()
106 //@@@ Release bitmaps
108 if (file != 0) {
109 fclose(file);
110 file = 0;
115 glyph* TeXFont_PK::getGlyph(quint16 ch, bool generateCharacterPixmap, const QColor& color)
117 #ifdef DEBUG_PK
118 kDebug(kvs::dvi) << "TeXFont_PK::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )";
119 #endif
121 // Paranoia checks
122 if (ch >= TeXFontDefinition::max_num_of_chars_in_font) {
123 kError(kvs::dvi) << "TeXFont_PK::getGlyph(): Argument is too big." << endl;
124 return glyphtable;
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
134 if (g->addr == 0) {
135 kError(kvs::dvi) << i18n("TexFont_PK::operator[]: Character %1 not defined in font %2", ch, parent->filename) << endl;
136 g->addr = -1;
137 return g;
140 // If the character has already been marked as missing, just
141 // return a pointer to the glyph (which will then be empty)
142 if (g->addr == -1)
143 return g;
145 // Otherwise, try to load the character
146 fseek(file, g->addr, 0);
147 read_PK_char(ch);
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) {
151 g->addr = -1;
152 return g;
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)) {
161 g->color = color;
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
198 // in other words,
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);
213 bit = bit & 1;
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++) {
230 quint32 value = 0;
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++) {
250 quint32 value = 0;
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];
279 } else {
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);
304 destScanLine++;
305 srcScanLine++;
310 g->shrunkenCharacter = im32;
312 return g;
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] = {
345 0x0, 0x1, 0x3, 0x7,
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,
353 0xffffffff
357 #define PK_ID 89
358 #define PK_CMD_START 240
359 #define PK_X1 240
360 #define PK_X2 241
361 #define PK_X3 242
362 #define PK_X4 243
363 #define PK_Y 244
364 #define PK_POST 245
365 #define PK_NOOP 246
366 #define PK_PRE 247
369 int TeXFont_PK::PK_get_nyb(FILE *fp)
371 #ifdef DEBUG_PK
372 kDebug(kvs::dvi) << "PK_get_nyb";
373 #endif
375 unsigned temp;
376 if (PK_bitpos < 0) {
377 PK_input_byte = one(fp);
378 PK_bitpos = 4;
380 temp = PK_input_byte >> PK_bitpos;
381 PK_bitpos -= 4;
382 return (temp & 0xf);
386 int TeXFont_PK::PK_packed_num(FILE *fp)
388 #ifdef DEBUG_PK
389 kDebug(kvs::dvi) << "PK_packed_num";
390 #endif
392 int i, j;
394 if ((i = PK_get_nyb(fp)) == 0) {
395 do {
396 j = PK_get_nyb(fp);
397 ++i;
399 while (j == 0);
400 while (i > 0) {
401 j = (j << 4) | PK_get_nyb(fp);
402 --i;
404 return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
406 else {
407 if (i <= PK_dyn_f) return i;
408 if (i < 14)
409 return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
410 + PK_dyn_f + 1);
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()
420 #ifdef DEBUG_PK
421 kDebug(kvs::dvi) << "TeXFont_PK::PK_skip_specials() called";
422 #endif
424 int i,j;
425 register FILE *fp = file;
427 #ifdef DEBUG_PK
428 if (fp == 0)
429 kDebug(kvs::dvi) << "TeXFont_PK::PK_skip_specials(): file == 0";
430 #endif
432 do {
433 PK_flag_byte = one(fp);
434 if (PK_flag_byte >= PK_CMD_START) {
435 switch (PK_flag_byte) {
436 case PK_X1 :
437 case PK_X2 :
438 case PK_X3 :
439 case PK_X4 :
440 i = 0;
441 for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
442 i = (i << 8) | one(fp);
443 while (i--) (void) one(fp);
444 break;
445 case PK_Y :
446 (void) four(fp);
447 case PK_POST :
448 case PK_NOOP :
449 break;
450 default :
451 oops(i18n("Unexpected %1 in PK file %2", PK_flag_byte, parent->filename) );
452 break;
456 while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
458 #ifdef DEBUG_PK
459 kDebug(kvs::dvi) << "TeXFont_PK::PK_skip_specials() ended";
460 #endif
464 void TeXFont_PK::read_PK_char(unsigned int ch)
466 #ifdef DEBUG_PK
467 kDebug(kvs::dvi) << "read_PK_char";
468 #endif
470 int i, j;
471 int n;
472 int row_bit_pos;
473 bool paint_switch;
474 quint32* cp;
475 register class glyph *g;
476 register FILE *fp = file;
477 long fpwidth;
478 quint32 word = 0;
479 int word_weight, bytes_wide;
480 int rows_left, h_bit, count;
482 g = glyphtable + ch;
483 PK_flag_byte = g->x2;
484 PK_dyn_f = PK_flag_byte >> 4;
485 paint_switch = ((PK_flag_byte & 8) != 0);
486 PK_flag_byte &= 0x7;
487 if (PK_flag_byte == 7)
488 n = 4;
489 else
490 if (PK_flag_byte > 3)
491 n = 2;
492 else
493 n = 1;
495 #ifdef DEBUG_PK
496 kDebug(kvs::dvi) << "loading pk char " << ch << ", char type " << n;
497 #endif
499 if (characterBitmaps[ch] == 0)
500 characterBitmaps[ch] = new bitmap();
503 * now read rest of character preamble
505 if (n != 4)
506 fpwidth = num(fp, 3);
507 else {
508 fpwidth = sfour(fp);
509 (void) four(fp); /* horizontal escapement */
511 (void) num(fp, n); /* vertical escapement */
513 unsigned long w, h;
515 w = num(fp, n);
516 h = num(fp, n);
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;
522 g->x = snum(fp, n);
523 g->y = snum(fp, n);
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;
540 PK_bitpos = -1;
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.
553 #ifdef DEBUG_PK
554 kDebug(kvs::dvi) << "big Endian byte ordering";
555 #endif
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);
561 row_bit_pos = 32;
562 for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
563 if (--PK_bitpos < 0) {
564 word = one(fp);
565 PK_bitpos = 7;
567 if (--row_bit_pos < 0) {
568 cp++;
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;
578 PK_repeat_count = 0;
579 word_weight = 32;
580 word = 0;
581 while (rows_left > 0) {
582 count = PK_packed_num(fp);
583 while (count > 0) {
584 if (count < word_weight && count < h_bit) {
585 h_bit -= count;
586 word_weight -= count;
587 if (paint_switch)
588 word |= bit_masks[count] << word_weight;
589 count = 0;
590 } else
591 if (count >= h_bit && h_bit <= word_weight) {
592 if (paint_switch)
593 word |= bit_masks[h_bit] << (word_weight - h_bit);
594 *cp++ = word;
595 /* "output" row(s) */
596 for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
597 *cp = *SUB(cp, bytes_wide);
598 ++cp;
600 rows_left -= PK_repeat_count + 1;
601 PK_repeat_count = 0;
602 word = 0;
603 word_weight = 32;
604 count -= h_bit;
605 h_bit = characterBitmaps[ch]->w;
606 } else {
607 if (paint_switch)
608 word |= bit_masks[word_weight];
609 *cp++ = word;
610 word = 0;
611 count -= word_weight;
612 h_bit -= word_weight;
613 word_weight = 32;
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];
631 bitmapData++;
634 } else {
636 // Routines for small Endian start here. This applies e.g. to
637 // Intel and Alpha processors.
639 #ifdef DEBUG_PK
640 kDebug(kvs::dvi) << "small Endian byte ordering";
641 #endif
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);
647 row_bit_pos = -1;
648 for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
649 if (--PK_bitpos < 0) {
650 word = one(fp);
651 PK_bitpos = 7;
653 if (++row_bit_pos >= 32) {
654 cp++;
655 row_bit_pos = 0;
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;
664 PK_repeat_count = 0;
665 word_weight = 32;
666 word = 0;
667 while (rows_left > 0) {
668 count = PK_packed_num(fp);
669 while (count > 0) {
670 if (count < word_weight && count < h_bit) {
671 if (paint_switch)
672 word |= bit_masks[count] << (32 - word_weight);
673 h_bit -= count;
674 word_weight -= count;
675 count = 0;
676 } else
677 if (count >= h_bit && h_bit <= word_weight) {
678 if (paint_switch)
679 word |= bit_masks[h_bit] << (32 - word_weight);
680 *cp++ = word;
681 /* "output" row(s) */
682 for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
683 *cp = *SUB(cp, bytes_wide);
684 ++cp;
686 rows_left -= PK_repeat_count + 1;
687 PK_repeat_count = 0;
688 word = 0;
689 word_weight = 32;
690 count -= h_bit;
691 h_bit = characterBitmaps[ch]->w;
692 } else {
693 if (paint_switch)
694 word |= bit_masks[word_weight] << (32 - word_weight);
695 *cp++ = word;
696 word = 0;
697 count -= word_weight;
698 h_bit -= word_weight;
699 word_weight = 32;
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()
715 #ifdef DEBUG_PK
716 kDebug(kvs::dvi) << "TeXFont_PK::read_PK_index() called";
717 #endif
719 if (file == 0) {
720 kError(kvs::dvi) << "TeXFont_PK::read_PK_index(): file == 0" << endl;
721 return;
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;
727 return;
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);
737 if (hppp != vppp)
738 kWarning(kvs::dvi) << i18n("Font has non-square aspect ratio ") << vppp << ":" << hppp ;
740 // Read glyph directory (really a whole pass over the file).
741 for (;;) {
742 int bytes_left, flag_low_bits;
743 unsigned int ch;
745 PK_skip_specials();
746 if (PK_flag_byte == PK_POST)
747 break;
748 flag_low_bits = PK_flag_byte & 0x7;
749 if (flag_low_bits == 7) {
750 bytes_left = four(file);
751 ch = four(file);
752 } else
753 if (flag_low_bits > 3) {
754 bytes_left = ((flag_low_bits - 4) << 16) + two(file);
755 ch = one(file);
756 } else {
757 bytes_left = (flag_low_bits << 8) + one(file);
758 ch = one(file);
761 glyphtable[ch].addr = ftell(file);
762 glyphtable[ch].x2 = PK_flag_byte;
763 fseek(file, (long) bytes_left, SEEK_CUR);
764 #ifdef DEBUG_PK
765 kDebug(kvs::dvi) << "Scanning pk char " << ch << "at " << glyphtable[ch].addr;
766 #endif
768 #ifdef DEBUG_PK
769 kDebug(kvs::dvi) << "TeXFont_PK::read_PK_index() called";
770 #endif