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 }