File indexing completed on 2024-05-12 04:33:59
0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*- 0002 /* 0003 * SPDX-FileCopyrightText: 1994 Paul Vojta. All rights reserved. 0004 * 0005 * SPDX-License-Identifier: BSD-2-Clause 0006 * 0007 * NOTE: 0008 * xdvi is based on prior work as noted in the modification history, below. 0009 */ 0010 0011 /* 0012 * DVI previewer for X. 0013 * 0014 * Eric Cooper, CMU, September 1985. 0015 * 0016 * Code derived from dvi-imagen.c. 0017 * 0018 * Modification history: 0019 * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS. 0020 * 7/1988 Modified for X.11 --Mark Eichin, MIT 0021 * 12/1988 Added 'R' option, toolkit, magnifying glass 0022 * --Paul Vojta, UC Berkeley. 0023 * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto 0024 * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ. 0025 * 3/1990 Added VMS support --Scott Allendorf, U of Iowa 0026 * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem 0027 * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen 0028 * and Lee Hetherington, MIT 0029 * 4/1994 Added DPS support, bounding box 0030 * --Ricardo Telichevesky 0031 * and Luis Miguel Silveira, MIT RLE. 0032 */ 0033 0034 #include <config.h> 0035 0036 #include "TeXFont_PK.h" 0037 #include "debug_dvi.h" 0038 #include "fontpool.h" 0039 #include "xdvi.h" 0040 0041 #include <KLocalizedString> 0042 0043 #include <QFile> 0044 #include <QImage> 0045 0046 #include <cmath> 0047 #include <math.h> 0048 0049 //#define DEBUG_PK 0050 0051 #define PK_PRE 247 0052 #define PK_ID 89 0053 #define PK_MAGIC (PK_PRE << 8) + PK_ID 0054 0055 extern void oops(const QString &message); 0056 0057 TeXFont_PK::TeXFont_PK(TeXFontDefinition *parent) 0058 : TeXFont(parent) 0059 { 0060 #ifdef DEBUG_PK 0061 qCDebug(OkularDviDebug) << "TeXFont_PK::TeXFont_PK( parent=" << parent << ")"; 0062 #endif 0063 0064 for (auto &characterBitmap : characterBitmaps) { 0065 characterBitmap = nullptr; 0066 } 0067 file = fopen(QFile::encodeName(parent->filename).constData(), "r"); 0068 if (file == nullptr) { 0069 qCCritical(OkularDviDebug) << i18n("Cannot open font file %1.", parent->filename); 0070 } 0071 #ifdef DEBUG_PK 0072 else 0073 qCDebug(OkularDviDebug) << "TeXFont_PK::TeXFont_PK(): file opened successfully"; 0074 #endif 0075 0076 read_PK_index(); 0077 0078 #ifdef DEBUG_PK 0079 qCDebug(OkularDviDebug) << "TeXFont_PK::TeXFont_PK() ended"; 0080 #endif 0081 } 0082 0083 TeXFont_PK::~TeXFont_PK() 0084 { 0085 //@@@ Release bitmaps 0086 for (bitmap *characterBitmap : characterBitmaps) { 0087 delete characterBitmap; 0088 } 0089 0090 if (file != nullptr) { 0091 fclose(file); 0092 file = nullptr; 0093 } 0094 } 0095 0096 glyph *TeXFont_PK::getGlyph(quint16 ch, bool generateCharacterPixmap, const QColor &color) 0097 { 0098 #ifdef DEBUG_PK 0099 qCDebug(OkularDviDebug) << "TeXFont_PK::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )"; 0100 #endif 0101 0102 // Paranoia checks 0103 if (ch >= TeXFontDefinition::max_num_of_chars_in_font) { 0104 qCCritical(OkularDviDebug) << "TeXFont_PK::getGlyph(): Argument is too big."; 0105 return glyphtable; 0106 } 0107 0108 // This is the address of the glyph that will be returned. 0109 class glyph *g = glyphtable + ch; 0110 0111 // Check if the glyph is loaded. If not, load it now. 0112 if (characterBitmaps[ch] == nullptr) { 0113 // If the character is not defined in the PK file, mark the 0114 // character as missing, and print an error message 0115 if (g->addr == 0) { 0116 qCCritical(OkularDviDebug) << i18n("TexFont_PK::operator[]: Character %1 not defined in font %2", ch, parent->filename); 0117 g->addr = -1; 0118 return g; 0119 } 0120 0121 // If the character has already been marked as missing, just 0122 // return a pointer to the glyph (which will then be empty) 0123 if (g->addr == -1) { 0124 return g; 0125 } 0126 0127 // Otherwise, try to load the character 0128 fseek(file, g->addr, 0); 0129 read_PK_char(ch); 0130 // Check if the character could be loaded. If not, mark the 0131 // character as 'missing', and return a pointer. 0132 if (characterBitmaps[ch]->bits == nullptr) { 0133 g->addr = -1; 0134 return g; 0135 } 0136 } 0137 0138 // At this point, g points to a properly loaded character. Generate 0139 // a smoothly scaled QPixmap if the user asks for it. 0140 if ((generateCharacterPixmap == true) && ((g->shrunkenCharacter.isNull()) || (color != g->color)) && (characterBitmaps[ch]->w != 0)) { 0141 g->color = color; 0142 double shrinkFactor = 1200 / parent->displayResolution_in_dpi; 0143 0144 // All is fine? Then we rescale the bitmap in order to produce the 0145 // required pixmap. Rescaling a character, however, is an art 0146 // that requires some explanation... 0147 // 0148 // If we would just divide the size of the character and the 0149 // coordinates by the shrink factor, then the result would look 0150 // quite ugly: due to the inevitable rounding errors in the 0151 // integer arithmetic, the characters would be displaced by up to 0152 // a pixel. That doesn't sound much, but on low-resolution 0153 // devices, such as a notebook screen, the effect would be a 0154 // "dancing line" of characters, which looks really bad. 0155 0156 // Calculate the coordinates of the hot point in the shrunken 0157 // bitmap. For simplicity, let us consider the x-coordinate 0158 // first. In principle, the hot point should have an x-coordinate 0159 // of (g->x/shrinkFactor). That, however, will generally NOT be an 0160 // integral number. The cure is to translate the source image 0161 // somewhat, so that the x-coordinate of the hot point falls onto 0162 // the round-up of this number, i.e. 0163 g->x2 = (int)ceil(g->x / shrinkFactor); 0164 0165 // Translating and scaling then means that the pixel in the scaled 0166 // image which covers the range [x,x+1) corresponds to the range 0167 // [x*shrinkFactor+srcXTrans, (x+1)*shrinkFactor+srcXTrans), where 0168 // srcXTrans is the following NEGATIVE number 0169 double srcXTrans = shrinkFactor * (g->x / shrinkFactor - ceil(g->x / shrinkFactor)); 0170 0171 // How big will the shrunken bitmap then become? If shrunk_width 0172 // denotes that width of the scaled image, and 0173 // characterBitmaps[ch]->w the width of the original image, we 0174 // need to make sure that the following inequality holds: 0175 // 0176 // shrunk_width*shrinkFactor+srcXTrans >= characterBitmaps[ch]->w 0177 // 0178 // in other words, 0179 int shrunk_width = (int)ceil((characterBitmaps[ch]->w - srcXTrans) / shrinkFactor); 0180 0181 // Now do the same for the y-coordinate 0182 g->y2 = (int)ceil(g->y / shrinkFactor); 0183 double srcYTrans = shrinkFactor * (g->y / shrinkFactor - ceil(g->y / shrinkFactor)); 0184 int shrunk_height = (int)ceil((characterBitmaps[ch]->h - srcYTrans) / shrinkFactor); 0185 0186 // Turn the image into 8 bit 0187 QByteArray translated(characterBitmaps[ch]->w * characterBitmaps[ch]->h, '\0'); 0188 quint8 *data = (quint8 *)translated.data(); 0189 for (int x = 0; x < characterBitmaps[ch]->w; x++) { 0190 for (int y = 0; y < characterBitmaps[ch]->h; y++) { 0191 quint8 bit = *(characterBitmaps[ch]->bits + characterBitmaps[ch]->bytes_wide * y + (x >> 3)); 0192 bit = bit >> (x & 7); 0193 bit = bit & 1; 0194 data[characterBitmaps[ch]->w * y + x] = bit; 0195 } 0196 } 0197 0198 // Now shrink the image. We shrink the X-direction first 0199 QByteArray xshrunk(shrunk_width * characterBitmaps[ch]->h, '\0'); 0200 quint8 *xdata = (quint8 *)xshrunk.data(); 0201 0202 // Do the shrinking. The pixel (x,y) that we want to calculate 0203 // corresponds to the line segment from 0204 // 0205 // [shrinkFactor*x+srcXTrans, shrinkFactor*(x+1)+srcXTrans) 0206 // 0207 // The trouble is, these numbers are in general no integers. 0208 0209 for (int y = 0; y < characterBitmaps[ch]->h; y++) { 0210 for (int x = 0; x < shrunk_width; x++) { 0211 quint32 value = 0; 0212 double destStartX = shrinkFactor * x + srcXTrans; 0213 double destEndX = shrinkFactor * (x + 1) + srcXTrans; 0214 for (int srcX = (int)ceil(destStartX); srcX < floor(destEndX); srcX++) { 0215 if ((srcX >= 0) && (srcX < characterBitmaps[ch]->w)) { 0216 value += data[characterBitmaps[ch]->w * y + srcX] * 255; 0217 } 0218 } 0219 0220 if (destStartX >= 0.0) { 0221 value += (quint32)(255.0 * (ceil(destStartX) - destStartX) * data[characterBitmaps[ch]->w * y + (int)floor(destStartX)]); 0222 } 0223 if (floor(destEndX) < characterBitmaps[ch]->w) { 0224 value += (quint32)(255.0 * (destEndX - floor(destEndX)) * data[characterBitmaps[ch]->w * y + (int)floor(destEndX)]); 0225 } 0226 0227 xdata[shrunk_width * y + x] = (int)(value / shrinkFactor + 0.5); 0228 } 0229 } 0230 0231 // Now shrink the Y-direction 0232 QByteArray xyshrunk(shrunk_width * shrunk_height, '\0'); 0233 quint8 *xydata = (quint8 *)xyshrunk.data(); 0234 for (int x = 0; x < shrunk_width; x++) { 0235 for (int y = 0; y < shrunk_height; y++) { 0236 quint32 value = 0; 0237 double destStartY = shrinkFactor * y + srcYTrans; 0238 double destEndY = shrinkFactor * (y + 1) + srcYTrans; 0239 for (int srcY = (int)ceil(destStartY); srcY < floor(destEndY); srcY++) { 0240 if ((srcY >= 0) && (srcY < characterBitmaps[ch]->h)) { 0241 value += xdata[shrunk_width * srcY + x]; 0242 } 0243 } 0244 0245 if (destStartY >= 0.0) { 0246 value += (quint32)((ceil(destStartY) - destStartY) * xdata[shrunk_width * (int)floor(destStartY) + x]); 0247 } 0248 if (floor(destEndY) < characterBitmaps[ch]->h) { 0249 value += (quint32)((destEndY - floor(destEndY)) * xdata[shrunk_width * (int)floor(destEndY) + x]); 0250 } 0251 0252 xydata[shrunk_width * y + x] = (int)(value / shrinkFactor); 0253 } 0254 } 0255 0256 QImage im32(shrunk_width, shrunk_height, QImage::Format_ARGB32); 0257 // Do QPixmaps fully support the alpha channel? If yes, we use 0258 // that. Otherwise, use other routines as a fallback 0259 if (parent->font_pool->QPixmapSupportsAlpha) { 0260 // If the alpha channel is properly supported, we set the 0261 // character glyph to a colored rectangle, and define the 0262 // character outline only using the alpha channel. That ensures 0263 // good quality rendering for overlapping characters. 0264 im32.fill(qRgb(color.red(), color.green(), color.blue())); 0265 for (int y = 0; y < shrunk_height; y++) { 0266 quint8 *destScanLine = (quint8 *)im32.scanLine(y); 0267 for (int col = 0; col < shrunk_width; col++) { 0268 destScanLine[4 * col + 3] = xydata[shrunk_width * y + col]; 0269 } 0270 } 0271 } else { 0272 // If the alpha channel is not supported... QT seems to turn the 0273 // alpha channel into a crude bitmap which is used to mask the 0274 // resulting QPixmap. In this case, we define the character 0275 // outline using the image data, and use the alpha channel only 0276 // to store "maximally opaque" or "completely transparent" 0277 // values. When characters are rendered, overlapping characters 0278 // are no longer correctly drawn, but quality is still 0279 // sufficient for most purposes. One notable exception is output 0280 // from the gftodvi program, which will be partially unreadable. 0281 quint16 rInv = 0xFF - color.red(); 0282 quint16 gInv = 0xFF - color.green(); 0283 quint16 bInv = 0xFF - color.blue(); 0284 0285 quint8 *srcScanLine = xydata; 0286 for (int y = 0; y < shrunk_height; y++) { 0287 unsigned int *destScanLine = reinterpret_cast<unsigned int *>(im32.scanLine(y)); 0288 for (int col = 0; col < shrunk_width; col++) { 0289 quint16 data = *srcScanLine; 0290 // The value stored in "data" now has the following meaning: 0291 // data = 0 -> white; data = 0xff -> use "color" 0292 *destScanLine = qRgba(0xFF - (rInv * data + 0x7F) / 0xFF, 0xFF - (gInv * data + 0x7F) / 0xFF, 0xFF - (bInv * data + 0x7F) / 0xFF, (data > 0x03) ? 0xff : 0x00); 0293 destScanLine++; 0294 srcScanLine++; 0295 } 0296 } 0297 } 0298 0299 g->shrunkenCharacter = im32; 0300 } 0301 return g; 0302 } 0303 0304 #define ADD(a, b) (reinterpret_cast<quint32 *>(((char *)a) + b)) 0305 #define SUB(a, b) (reinterpret_cast<quint32 *>(((char *)a) - b)) 0306 0307 // This table is used for changing the bit order in a byte. The 0308 // expression bitflp[byte] takes a byte in big endian and gives the 0309 // little endian equivalent of that. 0310 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, 0311 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, 0312 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, 0313 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, 0314 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, 0315 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, 0316 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}; 0317 0318 static const quint32 bit_masks[33] = {0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0319 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; 0320 0321 #define PK_ID 89 0322 #define PK_CMD_START 240 0323 #define PK_X1 240 0324 #define PK_X2 241 0325 #define PK_X3 242 0326 #define PK_X4 243 0327 #define PK_Y 244 0328 #define PK_POST 245 0329 #define PK_NOOP 246 0330 #define PK_PRE 247 0331 0332 int TeXFont_PK::PK_get_nyb(FILE *fp) 0333 { 0334 #ifdef DEBUG_PK 0335 qCDebug(OkularDviDebug) << "PK_get_nyb"; 0336 #endif 0337 0338 unsigned temp; 0339 if (PK_bitpos < 0) { 0340 PK_input_byte = one(fp); 0341 PK_bitpos = 4; 0342 } 0343 temp = PK_input_byte >> PK_bitpos; 0344 PK_bitpos -= 4; 0345 return (temp & 0xf); 0346 } 0347 0348 int TeXFont_PK::PK_packed_num(FILE *fp) 0349 { 0350 #ifdef DEBUG_PK 0351 qCDebug(OkularDviDebug) << "PK_packed_num"; 0352 #endif 0353 0354 int i, j; 0355 0356 if ((i = PK_get_nyb(fp)) == 0) { 0357 do { 0358 j = PK_get_nyb(fp); 0359 ++i; 0360 } while (j == 0); 0361 while (i > 0) { 0362 j = (j << 4) | PK_get_nyb(fp); 0363 --i; 0364 } 0365 return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f); 0366 } else { 0367 if (i <= PK_dyn_f) { 0368 return i; 0369 } 0370 if (i < 14) { 0371 return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp) + PK_dyn_f + 1); 0372 } 0373 if (i == 14) { 0374 PK_repeat_count = PK_packed_num(fp); 0375 } else { 0376 PK_repeat_count = 1; 0377 } 0378 return PK_packed_num(fp); 0379 } 0380 } 0381 0382 void TeXFont_PK::PK_skip_specials() 0383 { 0384 #ifdef DEBUG_PK 0385 qCDebug(OkularDviDebug) << "TeXFont_PK::PK_skip_specials() called"; 0386 #endif 0387 0388 int i, j; 0389 FILE *fp = file; 0390 0391 #ifdef DEBUG_PK 0392 if (fp == 0) 0393 qCDebug(OkularDviDebug) << "TeXFont_PK::PK_skip_specials(): file == 0"; 0394 #endif 0395 0396 do { 0397 PK_flag_byte = one(fp); 0398 if (PK_flag_byte >= PK_CMD_START) { 0399 switch (PK_flag_byte) { 0400 case PK_X1: 0401 case PK_X2: 0402 case PK_X3: 0403 case PK_X4: 0404 i = 0; 0405 for (j = PK_CMD_START; j <= PK_flag_byte; ++j) { 0406 i = (i << 8) | one(fp); 0407 } 0408 while (i--) { 0409 (void)one(fp); 0410 } 0411 break; 0412 case PK_Y: 0413 (void)four(fp); 0414 case PK_POST: 0415 case PK_NOOP: 0416 break; 0417 default: 0418 oops(i18n("Unexpected %1 in PK file %2", PK_flag_byte, parent->filename)); 0419 break; 0420 } 0421 } 0422 } while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START); 0423 0424 #ifdef DEBUG_PK 0425 qCDebug(OkularDviDebug) << "TeXFont_PK::PK_skip_specials() ended"; 0426 #endif 0427 } 0428 0429 void TeXFont_PK::read_PK_char(unsigned int ch) 0430 { 0431 #ifdef DEBUG_PK 0432 qCDebug(OkularDviDebug) << "read_PK_char"; 0433 #endif 0434 0435 int i, j; 0436 int n; 0437 int row_bit_pos; 0438 bool paint_switch; 0439 quint32 *cp; 0440 class glyph *g; 0441 FILE *fp = file; 0442 long fpwidth; 0443 quint32 word = 0; 0444 int word_weight, bytes_wide; 0445 int rows_left, h_bit, count; 0446 0447 g = glyphtable + ch; 0448 PK_flag_byte = g->x2; 0449 PK_dyn_f = PK_flag_byte >> 4; 0450 paint_switch = ((PK_flag_byte & 8) != 0); 0451 PK_flag_byte &= 0x7; 0452 if (PK_flag_byte == 7) { 0453 n = 4; 0454 } else if (PK_flag_byte > 3) { 0455 n = 2; 0456 } else { 0457 n = 1; 0458 } 0459 0460 #ifdef DEBUG_PK 0461 qCDebug(OkularDviDebug) << "loading pk char " << ch << ", char type " << n; 0462 #endif 0463 0464 if (characterBitmaps[ch] == nullptr) { 0465 characterBitmaps[ch] = new bitmap(); 0466 } 0467 0468 /* 0469 * now read rest of character preamble 0470 */ 0471 if (n != 4) { 0472 fpwidth = num(fp, 3); 0473 } else { 0474 fpwidth = sfour(fp); 0475 (void)four(fp); /* horizontal escapement */ 0476 } 0477 (void)num(fp, n); /* vertical escapement */ 0478 { 0479 unsigned long w, h; 0480 0481 w = num(fp, n); 0482 h = num(fp, n); 0483 if (w > 0x7fff || h > 0x7fff) { 0484 oops(i18n("The character %1 is too large in file %2", ch, parent->filename)); 0485 } 0486 characterBitmaps[ch]->w = w; 0487 characterBitmaps[ch]->h = h; 0488 } 0489 g->x = snum(fp, n); 0490 g->y = snum(fp, n); 0491 0492 g->dvi_advance_in_units_of_design_size_by_2e20 = fpwidth; 0493 0494 { 0495 /* width must be multiple of 16 bits for raster_op */ 0496 characterBitmaps[ch]->bytes_wide = ROUNDUP((int)characterBitmaps[ch]->w, 32) * 4; 0497 unsigned int size = characterBitmaps[ch]->bytes_wide * characterBitmaps[ch]->h; 0498 characterBitmaps[ch]->bits = new char[size != 0 ? size : 1]; 0499 } 0500 0501 cp = reinterpret_cast<quint32 *>(characterBitmaps[ch]->bits); 0502 0503 /* 0504 * read character data into *cp 0505 */ 0506 bytes_wide = ROUNDUP((int)characterBitmaps[ch]->w, 32) * 4; 0507 PK_bitpos = -1; 0508 0509 // The routines which read the character depend on the bit 0510 // ordering. In principle, the bit order should be detected at 0511 // compile time and the proper routing chosen. For the moment, as 0512 // autoconf is somewhat complicated for the author, we prefer a 0513 // simpler -even if somewhat slower approach and detect the ordering 0514 // at runtime. That should of course be changed in the future. 0515 0516 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 0517 // Routine for big Endian machines. Applies e.g. to Motorola and 0518 // (Ultra-)Sparc processors. 0519 0520 #ifdef DEBUG_PK 0521 qCDebug(OkularDviDebug) << "big Endian byte ordering"; 0522 #endif 0523 0524 if (PK_dyn_f == 14) { /* get raster by bits */ 0525 memset(characterBitmaps[ch]->bits, 0, (int)characterBitmaps[ch]->h * bytes_wide); 0526 for (i = 0; i < (int)characterBitmaps[ch]->h; i++) { /* get all rows */ 0527 cp = ADD(characterBitmaps[ch]->bits, i * bytes_wide); 0528 row_bit_pos = 32; 0529 for (j = 0; j < (int)characterBitmaps[ch]->w; j++) { /* get one row */ 0530 if (--PK_bitpos < 0) { 0531 word = one(fp); 0532 PK_bitpos = 7; 0533 } 0534 if (--row_bit_pos < 0) { 0535 cp++; 0536 row_bit_pos = 32 - 1; 0537 } 0538 if (word & (1 << PK_bitpos)) { 0539 *cp |= 1 << row_bit_pos; 0540 } 0541 } 0542 } 0543 } else { /* get packed raster */ 0544 rows_left = characterBitmaps[ch]->h; 0545 h_bit = characterBitmaps[ch]->w; 0546 PK_repeat_count = 0; 0547 word_weight = 32; 0548 word = 0; 0549 while (rows_left > 0) { 0550 count = PK_packed_num(fp); 0551 while (count > 0) { 0552 if (count < word_weight && count < h_bit) { 0553 h_bit -= count; 0554 word_weight -= count; 0555 if (paint_switch) { 0556 word |= bit_masks[count] << word_weight; 0557 } 0558 count = 0; 0559 } else if (count >= h_bit && h_bit <= word_weight) { 0560 if (paint_switch) { 0561 word |= bit_masks[h_bit] << (word_weight - h_bit); 0562 } 0563 *cp++ = word; 0564 /* "output" row(s) */ 0565 for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) { 0566 *cp = *SUB(cp, bytes_wide); 0567 ++cp; 0568 } 0569 rows_left -= PK_repeat_count + 1; 0570 PK_repeat_count = 0; 0571 word = 0; 0572 word_weight = 32; 0573 count -= h_bit; 0574 h_bit = characterBitmaps[ch]->w; 0575 } else { 0576 if (paint_switch) { 0577 word |= bit_masks[word_weight]; 0578 } 0579 *cp++ = word; 0580 word = 0; 0581 count -= word_weight; 0582 h_bit -= word_weight; 0583 word_weight = 32; 0584 } 0585 } 0586 paint_switch = 1 - paint_switch; 0587 } 0588 if (cp != (reinterpret_cast<quint32 *>(characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h))) { 0589 oops(i18n("Wrong number of bits stored: char. %1, font %2", ch, parent->filename)); 0590 } 0591 if (rows_left != 0 || h_bit != characterBitmaps[ch]->w) { 0592 oops(i18n("Bad pk file (%1), too many bits", parent->filename)); 0593 } 0594 } 0595 0596 // The data in the bitmap is now in the processor's bit order, 0597 // that is, big endian. Since XWindows needs little endian, we 0598 // need to change the bit order now. 0599 unsigned char *bitmapData = (unsigned char *)characterBitmaps[ch]->bits; 0600 unsigned char *endOfData = bitmapData + characterBitmaps[ch]->bytes_wide * characterBitmaps[ch]->h; 0601 while (bitmapData < endOfData) { 0602 *bitmapData = bitflip[*bitmapData]; 0603 bitmapData++; 0604 } 0605 0606 } else { 0607 // Routines for small Endian start here. This applies e.g. to 0608 // Intel and Alpha processors. 0609 0610 #ifdef DEBUG_PK 0611 qCDebug(OkularDviDebug) << "small Endian byte ordering"; 0612 #endif 0613 0614 if (PK_dyn_f == 14) { /* get raster by bits */ 0615 memset(characterBitmaps[ch]->bits, 0, (int)characterBitmaps[ch]->h * bytes_wide); 0616 for (i = 0; i < (int)characterBitmaps[ch]->h; i++) { /* get all rows */ 0617 cp = ADD(characterBitmaps[ch]->bits, i * bytes_wide); 0618 row_bit_pos = -1; 0619 for (j = 0; j < (int)characterBitmaps[ch]->w; j++) { /* get one row */ 0620 if (--PK_bitpos < 0) { 0621 word = one(fp); 0622 PK_bitpos = 7; 0623 } 0624 if (++row_bit_pos >= 32) { 0625 cp++; 0626 row_bit_pos = 0; 0627 } 0628 if (word & (1 << PK_bitpos)) { 0629 *cp |= 1 << row_bit_pos; 0630 } 0631 } 0632 } 0633 } else { /* get packed raster */ 0634 rows_left = characterBitmaps[ch]->h; 0635 h_bit = characterBitmaps[ch]->w; 0636 PK_repeat_count = 0; 0637 word_weight = 32; 0638 word = 0; 0639 while (rows_left > 0) { 0640 count = PK_packed_num(fp); 0641 while (count > 0) { 0642 if (count < word_weight && count < h_bit) { 0643 if (paint_switch) { 0644 word |= bit_masks[count] << (32 - word_weight); 0645 } 0646 h_bit -= count; 0647 word_weight -= count; 0648 count = 0; 0649 } else if (count >= h_bit && h_bit <= word_weight) { 0650 if (paint_switch) { 0651 word |= bit_masks[h_bit] << (32 - word_weight); 0652 } 0653 *cp++ = word; 0654 /* "output" row(s) */ 0655 for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) { 0656 *cp = *SUB(cp, bytes_wide); 0657 ++cp; 0658 } 0659 rows_left -= PK_repeat_count + 1; 0660 PK_repeat_count = 0; 0661 word = 0; 0662 word_weight = 32; 0663 count -= h_bit; 0664 h_bit = characterBitmaps[ch]->w; 0665 } else { 0666 if (paint_switch) { 0667 word |= bit_masks[word_weight] << (32 - word_weight); 0668 } 0669 *cp++ = word; 0670 word = 0; 0671 count -= word_weight; 0672 h_bit -= word_weight; 0673 word_weight = 32; 0674 } 0675 } 0676 paint_switch = 1 - paint_switch; 0677 } 0678 if (cp != (reinterpret_cast<quint32 *>(characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h))) { 0679 oops(i18n("Wrong number of bits stored: char. %1, font %2", ch, parent->filename)); 0680 } 0681 if (rows_left != 0 || h_bit != characterBitmaps[ch]->w) { 0682 oops(i18n("Bad pk file (%1), too many bits", parent->filename)); 0683 } 0684 } 0685 } // endif: big or small Endian? 0686 } 0687 0688 void TeXFont_PK::read_PK_index() 0689 { 0690 #ifdef DEBUG_PK 0691 qCDebug(OkularDviDebug) << "TeXFont_PK::read_PK_index() called"; 0692 #endif 0693 0694 if (file == nullptr) { 0695 qCCritical(OkularDviDebug) << "TeXFont_PK::read_PK_index(): file == 0"; 0696 return; 0697 } 0698 0699 int magic = two(file); 0700 if (magic != PK_MAGIC) { 0701 qCCritical(OkularDviDebug) << "TeXFont_PK::read_PK_index(): file is not a PK file"; 0702 return; 0703 } 0704 0705 fseek(file, (long)one(file), SEEK_CUR); /* skip comment */ 0706 (void)four(file); /* skip design size */ 0707 0708 checksum = four(file); 0709 0710 int hppp = sfour(file); 0711 int vppp = sfour(file); 0712 if (hppp != vppp) { 0713 qCWarning(OkularDviDebug) << i18n("Font has non-square aspect ratio ") << vppp << ":" << hppp; 0714 } 0715 0716 // Read glyph directory (really a whole pass over the file). 0717 for (;;) { 0718 int bytes_left, flag_low_bits; 0719 unsigned int ch; 0720 0721 PK_skip_specials(); 0722 if (PK_flag_byte == PK_POST) { 0723 break; 0724 } 0725 flag_low_bits = PK_flag_byte & 0x7; 0726 if (flag_low_bits == 7) { 0727 bytes_left = four(file); 0728 ch = four(file); 0729 } else if (flag_low_bits > 3) { 0730 bytes_left = ((flag_low_bits - 4) << 16) + two(file); 0731 ch = one(file); 0732 } else { 0733 bytes_left = (flag_low_bits << 8) + one(file); 0734 ch = one(file); 0735 } 0736 0737 glyphtable[ch].addr = ftell(file); 0738 glyphtable[ch].x2 = PK_flag_byte; 0739 fseek(file, (long)bytes_left, SEEK_CUR); 0740 #ifdef DEBUG_PK 0741 qCDebug(OkularDviDebug) << "Scanning pk char " << ch << "at " << glyphtable[ch].addr; 0742 #endif 0743 } 0744 #ifdef DEBUG_PK 0745 qCDebug(OkularDviDebug) << "TeXFont_PK::read_PK_index() called"; 0746 #endif 0747 }