summaryrefslogtreecommitdiffstats
path: root/kdvi/TeXFont_PK.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /kdvi/TeXFont_PK.cpp
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdvi/TeXFont_PK.cpp')
-rw-r--r--kdvi/TeXFont_PK.cpp781
1 files changed, 781 insertions, 0 deletions
diff --git a/kdvi/TeXFont_PK.cpp b/kdvi/TeXFont_PK.cpp
new file mode 100644
index 00000000..6a3c9b3a
--- /dev/null
+++ b/kdvi/TeXFont_PK.cpp
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 1994 Paul Vojta. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * NOTE:
+ * xdvi is based on prior work as noted in the modification history, below.
+ */
+
+/*
+ * DVI previewer for X.
+ *
+ * Eric Cooper, CMU, September 1985.
+ *
+ * Code derived from dvi-imagen.c.
+ *
+ * Modification history:
+ * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
+ * 7/1988 Modified for X.11 --Mark Eichin, MIT
+ * 12/1988 Added 'R' option, toolkit, magnifying glass
+ * --Paul Vojta, UC Berkeley.
+ * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
+ * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
+ * 3/1990 Added VMS support --Scott Allendorf, U of Iowa
+ * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
+ * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
+ * and Lee Hetherington, MIT
+ * 4/1994 Added DPS support, bounding box
+ * --Ricardo Telichevesky
+ * and Luis Miguel Silveira, MIT RLE.
+ */
+
+#include <config.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <math.h>
+#include <qbitmap.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fontpool.h"
+#include "glyph.h"
+#include "xdvi.h"
+#include "TeXFontDefinition.h"
+#include "TeXFont_PK.h"
+
+
+//#define DEBUG_PK
+
+#define PK_PRE 247
+#define PK_ID 89
+#define PK_MAGIC (PK_PRE << 8) + PK_ID
+
+
+extern void oops(QString message);
+
+
+
+TeXFont_PK::TeXFont_PK(TeXFontDefinition *parent)
+ : TeXFont(parent)
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::TeXFont_PK( parent=" << parent << ")" << endl;
+#endif
+
+ for(unsigned int i=0; i<TeXFontDefinition::max_num_of_chars_in_font; i++)
+ characterBitmaps[i] = 0;
+ file = fopen(QFile::encodeName(parent->filename), "r");
+ if (file == 0)
+ kdError(4300) << i18n("Cannot open font file %1.").arg(parent->filename) << endl;
+#ifdef DEBUG_PK
+ else
+ kdDebug(4300) << "TeXFont_PK::TeXFont_PK(): file opened successfully" << endl;
+#endif
+
+ read_PK_index();
+
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::TeXFont_PK() ended" << endl;
+#endif
+}
+
+
+TeXFont_PK::~TeXFont_PK()
+{
+ //@@@ Release bitmaps
+
+ if (file != 0) {
+ fclose(file);
+ file = 0;
+ }
+}
+
+
+glyph* TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, const QColor& color)
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )" << endl;
+#endif
+
+ // Paranoia checks
+ if (ch >= TeXFontDefinition::max_num_of_chars_in_font) {
+ kdError(4300) << "TeXFont_PK::getGlyph(): Argument is too big." << endl;
+ return glyphtable;
+ }
+
+ // This is the address of the glyph that will be returned.
+ struct glyph *g = glyphtable+ch;
+
+ // Check if the glyph is loaded. If not, load it now.
+ if (characterBitmaps[ch] == 0) {
+ // If the character is not defined in the PK file, mark the
+ // character as missing, and print an error message
+ if (g->addr == 0) {
+ kdError(4300) << i18n("TexFont_PK::operator[]: Character %1 not defined in font %2").arg(ch).arg(parent->filename) << endl;
+ g->addr = -1;
+ return g;
+ }
+
+ // If the character has already been marked as missing, just
+ // return a pointer to the glyph (which will then be empty)
+ if (g->addr == -1)
+ return g;
+
+ // Otherwise, try to load the character
+ fseek(file, g->addr, 0);
+ read_PK_char(ch);
+ // Check if the character could be loaded. If not, mark the
+ // character as 'missing', and return a pointer.
+ if (characterBitmaps[ch]->bits == 0) {
+ g->addr = -1;
+ return g;
+ }
+ }
+
+ // At this point, g points to a properly loaded character. Generate
+ // a smoothly scaled QPixmap if the user asks for it.
+ if ((generateCharacterPixmap == true) &&
+ ((g->shrunkenCharacter.isNull()) || (color != g->color)) &&
+ (characterBitmaps[ch]->w != 0)) {
+ g->color = color;
+ double shrinkFactor = 1200 / parent->displayResolution_in_dpi;
+
+ // All is fine? Then we rescale the bitmap in order to produce the
+ // required pixmap. Rescaling a character, however, is an art
+ // that requires some explanation...
+ //
+ // If we would just divide the size of the character and the
+ // coordinates by the shrink factor, then the result would look
+ // quite ugly: due to the ineviatable rounding errors in the
+ // integer arithmetic, the characters would be displaced by up to
+ // a pixel. That doesn't sound much, but on low-resolution
+ // devices, such as a notebook screen, the effect would be a
+ // "dancing line" of characters, which looks really bad.
+
+ // Calculate the coordinates of the hot point in the shrunken
+ // bitmap. For simplicity, let us consider the x-coordinate
+ // first. In principle, the hot point should have an x-coordinate
+ // of (g->x/shrinkFactor). That, however, will generally NOT be an
+ // integral number. The cure is to translate the source image
+ // somewhat, so that the x-coordinate of the hot point falls onto
+ // the round-up of this number, i.e.
+ g->x2 = (int)ceil(g->x/shrinkFactor);
+
+ // Translating and scaling then means that the pixel in the scaled
+ // image which covers the range [x,x+1) corresponds to the range
+ // [x*shrinkFactor+srcXTrans, (x+1)*shrinkFactor+srcXTrans), where
+ // srcXTrans is the following NEGATIVE number
+ double srcXTrans = shrinkFactor * (g->x/shrinkFactor - ceil(g->x/shrinkFactor));
+
+ // How big will the shrunken bitmap then become? If shrunk_width
+ // denotes that width of the scaled image, and
+ // characterBitmaps[ch]->w the width of the orininal image, we
+ // need to make sure that the following inequality holds:
+ //
+ // shrunk_width*shrinkFactor+srcXTrans >= characterBitmaps[ch]->w
+ //
+ // in other words,
+ int shrunk_width = (int)ceil( (characterBitmaps[ch]->w - srcXTrans)/shrinkFactor );
+
+ // Now do the same for the y-coordinate
+ g->y2 = (int)ceil(g->y/shrinkFactor);
+ double srcYTrans = shrinkFactor * (g->y/shrinkFactor - ceil(g->y/shrinkFactor ));
+ int shrunk_height = (int)ceil( (characterBitmaps[ch]->h - srcYTrans)/shrinkFactor );
+
+ // Turn the image into 8 bit
+ QByteArray translated(characterBitmaps[ch]->w * characterBitmaps[ch]->h);
+ Q_UINT8 *data = (Q_UINT8 *)translated.data();
+ for(int x=0; x<characterBitmaps[ch]->w; x++)
+ for(int y=0; y<characterBitmaps[ch]->h; y++) {
+ Q_UINT8 bit = *(characterBitmaps[ch]->bits + characterBitmaps[ch]->bytes_wide*y + (x >> 3));
+ bit = bit >> (x & 7);
+ bit = bit & 1;
+ data[characterBitmaps[ch]->w*y + x] = bit;
+ }
+
+ // Now shrink the image. We shrink the X-direction first
+ QByteArray xshrunk(shrunk_width*characterBitmaps[ch]->h);
+ Q_UINT8 *xdata = (Q_UINT8 *)xshrunk.data();
+
+ // Do the shrinking. The pixel (x,y) that we want to calculate
+ // corresponds to the line segment from
+ //
+ // [shrinkFactor*x+srcXTrans, shrinkFactor*(x+1)+srcXTrans)
+ //
+ // The trouble is, these numbers are in general no integers.
+
+ for(int y=0; y<characterBitmaps[ch]->h; y++)
+ for(int x=0; x<shrunk_width; x++) {
+ Q_UINT32 value = 0;
+ double destStartX = shrinkFactor*x+srcXTrans;
+ double destEndX = shrinkFactor*(x+1)+srcXTrans;
+ for(int srcX=(int)ceil(destStartX); srcX<floor(destEndX); srcX++)
+ if ((srcX >= 0) && (srcX < characterBitmaps[ch]->w))
+ value += data[characterBitmaps[ch]->w*y + srcX] * 255;
+
+ if (destStartX >= 0.0)
+ value += (Q_UINT32) (255.0*(ceil(destStartX)-destStartX) * data[characterBitmaps[ch]->w*y + (int)floor(destStartX)]);
+ if (floor(destEndX) < characterBitmaps[ch]->w)
+ value += (Q_UINT32) (255.0*(destEndX-floor(destEndX)) * data[characterBitmaps[ch]->w*y + (int)floor(destEndX)]);
+
+ xdata[shrunk_width*y + x] = (int)(value/shrinkFactor + 0.5);
+ }
+
+ // Now shrink the Y-direction
+ QByteArray xyshrunk(shrunk_width*shrunk_height);
+ Q_UINT8 *xydata = (Q_UINT8 *)xyshrunk.data();
+ for(int x=0; x<shrunk_width; x++)
+ for(int y=0; y<shrunk_height; y++) {
+ Q_UINT32 value = 0;
+ double destStartY = shrinkFactor*y+srcYTrans;
+ double destEndY = shrinkFactor*(y+1)+srcYTrans;
+ for(int srcY=(int)ceil(destStartY); srcY<floor(destEndY); srcY++)
+ if ((srcY >= 0) && (srcY < characterBitmaps[ch]->h))
+ value += xdata[shrunk_width*srcY + x];
+
+ if (destStartY >= 0.0)
+ value += (Q_UINT32) ((ceil(destStartY)-destStartY) * xdata[shrunk_width*(int)floor(destStartY) + x]);
+ if (floor(destEndY) < characterBitmaps[ch]->h)
+ value += (Q_UINT32) ((destEndY-floor(destEndY)) * xdata[shrunk_width*(int)floor(destEndY) + x]);
+
+ xydata[shrunk_width*y + x] = (int)(value/shrinkFactor);
+ }
+
+ QImage im32(shrunk_width, shrunk_height, 32);
+ im32.setAlphaBuffer(true);
+ // Do QPixmaps fully support the alpha channel? If yes, we use
+ // that. Otherwise, use other routines as a fallback
+ if (parent->font_pool->QPixmapSupportsAlpha) {
+ // If the alpha channel is properly supported, we set the
+ // character glyph to a colored rectangle, and define the
+ // character outline only using the alpha channel. That ensures
+ // good quality rendering for overlapping characters.
+ im32.fill(qRgb(color.red(), color.green(), color.blue()));
+ for(Q_UINT16 y=0; y<shrunk_height; y++) {
+ Q_UINT8 *destScanLine = (Q_UINT8 *)im32.scanLine(y);
+ for(Q_UINT16 col=0; col<shrunk_width; col++)
+ destScanLine[4*col+3] = xydata[shrunk_width*y + col];
+ }
+ } else {
+ // If the alpha channel is not supported... QT seems to turn the
+ // alpha channel into a crude bitmap which is used to mask the
+ // resulting QPixmap. In this case, we define the character
+ // outline using the image data, and use the alpha channel only
+ // to store "maximally opaque" or "completely transparent"
+ // values. When characters are rendered, overlapping characters
+ // are no longer correctly drawn, but quality is still
+ // sufficient for most purposes. One notable exception is output
+ // from the gftodvi program, which will be partially unreadable.
+ Q_UINT16 rInv = 0xFF - color.red();
+ Q_UINT16 gInv = 0xFF - color.green();
+ Q_UINT16 bInv = 0xFF - color.blue();
+
+ Q_UINT8 *srcScanLine = xydata;
+ for(Q_UINT16 y=0; y<shrunk_height; y++) {
+ unsigned int *destScanLine = (unsigned int *)im32.scanLine(y);
+ for(Q_UINT16 col=0; col<shrunk_width; col++) {
+ Q_UINT16 data = *srcScanLine;
+ // The value stored in "data" now has the following meaning:
+ // data = 0 -> white; data = 0xff -> use "color"
+ *destScanLine = qRgba(0xFF - (rInv*data + 0x7F) / 0xFF,
+ 0xFF - (gInv*data + 0x7F) / 0xFF,
+ 0xFF - (bInv*data + 0x7F) / 0xFF,
+ (data > 0x03) ? 0xff : 0x00);
+ destScanLine++;
+ srcScanLine++;
+ }
+ }
+ }
+
+ g->shrunkenCharacter.convertFromImage(im32,0);
+ g->shrunkenCharacter.setOptimization(QPixmap::BestOptim);
+ }
+ return g;
+}
+
+
+
+#define ADD(a, b) ((Q_UINT32 *) (((char *) a) + b))
+#define SUB(a, b) ((Q_UINT32 *) (((char *) a) - b))
+
+
+
+// This table is used for changing the bit order in a byte. The
+// expression bitflp[byte] takes a byte in big endian and gives the
+// little endian equivalent of that.
+static const uchar bitflip[256] = {
+ 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
+ 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
+ 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
+ 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
+ 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+ 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
+ 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
+ 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
+ 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
+ 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+ 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
+ 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
+ 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
+ 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
+ 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+ 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
+};
+
+static Q_UINT32 bit_masks[33] = {
+ 0x0, 0x1, 0x3, 0x7,
+ 0xf, 0x1f, 0x3f, 0x7f,
+ 0xff, 0x1ff, 0x3ff, 0x7ff,
+ 0xfff, 0x1fff, 0x3fff, 0x7fff,
+ 0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
+ 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
+ 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
+ 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
+};
+
+
+#define PK_ID 89
+#define PK_CMD_START 240
+#define PK_X1 240
+#define PK_X2 241
+#define PK_X3 242
+#define PK_X4 243
+#define PK_Y 244
+#define PK_POST 245
+#define PK_NOOP 246
+#define PK_PRE 247
+
+
+int TeXFont_PK::PK_get_nyb(FILE *fp)
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "PK_get_nyb" << endl;
+#endif
+
+ unsigned temp;
+ if (PK_bitpos < 0) {
+ PK_input_byte = one(fp);
+ PK_bitpos = 4;
+ }
+ temp = PK_input_byte >> PK_bitpos;
+ PK_bitpos -= 4;
+ return (temp & 0xf);
+}
+
+
+int TeXFont_PK::PK_packed_num(FILE *fp)
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "PK_packed_num" << endl;
+#endif
+
+ int i,j;
+
+ if ((i = PK_get_nyb(fp)) == 0) {
+ do {
+ j = PK_get_nyb(fp);
+ ++i;
+ }
+ while (j == 0);
+ while (i > 0) {
+ j = (j << 4) | PK_get_nyb(fp);
+ --i;
+ }
+ return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
+ }
+ else {
+ if (i <= PK_dyn_f) return i;
+ if (i < 14)
+ return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
+ + PK_dyn_f + 1);
+ if (i == 14) PK_repeat_count = PK_packed_num(fp);
+ else PK_repeat_count = 1;
+ return PK_packed_num(fp);
+ }
+}
+
+
+void TeXFont_PK::PK_skip_specials()
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::PK_skip_specials() called" << endl;
+#endif
+
+ int i,j;
+ register FILE *fp = file;
+
+#ifdef DEBUG_PK
+ if (fp == 0)
+ kdDebug(4300) << "TeXFont_PK::PK_skip_specials(): file == 0" << endl;
+#endif
+
+ do {
+ PK_flag_byte = one(fp);
+ if (PK_flag_byte >= PK_CMD_START) {
+ switch (PK_flag_byte) {
+ case PK_X1 :
+ case PK_X2 :
+ case PK_X3 :
+ case PK_X4 :
+ i = 0;
+ for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
+ i = (i << 8) | one(fp);
+ while (i--) (void) one(fp);
+ break;
+ case PK_Y :
+ (void) four(fp);
+ case PK_POST :
+ case PK_NOOP :
+ break;
+ default :
+ oops(i18n("Unexpected %1 in PK file %2").arg(PK_flag_byte).arg(parent->filename) );
+ break;
+ }
+ }
+ }
+ while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
+
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::PK_skip_specials() ended" << endl;
+#endif
+}
+
+
+void TeXFont_PK::read_PK_char(unsigned int ch)
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "read_PK_char" << endl;
+#endif
+
+ int i, j;
+ int n;
+ int row_bit_pos;
+ bool paint_switch;
+ Q_UINT32 *cp;
+ register struct glyph *g;
+ register FILE *fp = file;
+ long fpwidth;
+ Q_UINT32 word = 0;
+ int word_weight, bytes_wide;
+ int rows_left, h_bit, count;
+
+ g = glyphtable + ch;
+ PK_flag_byte = g->x2;
+ PK_dyn_f = PK_flag_byte >> 4;
+ paint_switch = ((PK_flag_byte & 8) != 0);
+ PK_flag_byte &= 0x7;
+ if (PK_flag_byte == 7)
+ n = 4;
+ else
+ if (PK_flag_byte > 3)
+ n = 2;
+ else
+ n = 1;
+
+#ifdef DEBUG_PK
+ kdDebug(4300) << "loading pk char " << ch << ", char type " << n << endl;
+#endif
+
+ if (characterBitmaps[ch] == 0)
+ characterBitmaps[ch] = new bitmap();
+
+ /*
+ * now read rest of character preamble
+ */
+ if (n != 4)
+ fpwidth = num(fp, 3);
+ else {
+ fpwidth = sfour(fp);
+ (void) four(fp); /* horizontal escapement */
+ }
+ (void) num(fp, n); /* vertical escapement */
+ {
+ unsigned long w, h;
+
+ w = num(fp, n);
+ h = num(fp, n);
+ if (w > 0x7fff || h > 0x7fff)
+ oops(i18n("The character %1 is too large in file %2").arg(ch).arg(parent->filename));
+ characterBitmaps[ch]->w = w;
+ characterBitmaps[ch]->h = h;
+ }
+ g->x = snum(fp, n);
+ g->y = snum(fp, n);
+
+ g->dvi_advance_in_units_of_design_size_by_2e20 = fpwidth;
+
+ {
+ /* width must be multiple of 16 bits for raster_op */
+ characterBitmaps[ch]->bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, 32) * 4;
+ register unsigned int size = characterBitmaps[ch]->bytes_wide * characterBitmaps[ch]->h;
+ characterBitmaps[ch]->bits = new char[size != 0 ? size : 1];
+ }
+
+ cp = (Q_UINT32 *) characterBitmaps[ch]->bits;
+
+ /*
+ * read character data into *cp
+ */
+ bytes_wide = ROUNDUP((int) characterBitmaps[ch]->w, 32) * 4;
+ PK_bitpos = -1;
+
+ // The routines which read the character depend on the bit
+ // ordering. In principle, the bit order should be detected at
+ // compile time and the proper routing chosen. For the moment, as
+ // autoconf is somewhat complicated for the author, we prefer a
+ // simpler -even if somewhat slower approach and detect the ordering
+ // at runtime. That should of course be changed in the future.
+
+ int wordSize;
+ bool bigEndian;
+ qSysInfo (&wordSize, &bigEndian);
+
+ if (bigEndian) {
+ // Routine for big Endian machines. Applies e.g. to Motorola and
+ // (Ultra-)Sparc processors.
+
+#ifdef DEBUG_PK
+ kdDebug(4300) << "big Endian byte ordering" << endl;
+#endif
+
+ if (PK_dyn_f == 14) { /* get raster by bits */
+ memset(characterBitmaps[ch]->bits, 0, (int) characterBitmaps[ch]->h * bytes_wide);
+ for (i = 0; i < (int) characterBitmaps[ch]->h; i++) { /* get all rows */
+ cp = ADD(characterBitmaps[ch]->bits, i * bytes_wide);
+ row_bit_pos = 32;
+ for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
+ if (--PK_bitpos < 0) {
+ word = one(fp);
+ PK_bitpos = 7;
+ }
+ if (--row_bit_pos < 0) {
+ cp++;
+ row_bit_pos = 32 - 1;
+ }
+ if (word & (1 << PK_bitpos))
+ *cp |= 1 << row_bit_pos;
+ }
+ }
+ } else { /* get packed raster */
+ rows_left = characterBitmaps[ch]->h;
+ h_bit = characterBitmaps[ch]->w;
+ PK_repeat_count = 0;
+ word_weight = 32;
+ word = 0;
+ while (rows_left > 0) {
+ count = PK_packed_num(fp);
+ while (count > 0) {
+ if (count < word_weight && count < h_bit) {
+ h_bit -= count;
+ word_weight -= count;
+ if (paint_switch)
+ word |= bit_masks[count] << word_weight;
+ count = 0;
+ } else
+ if (count >= h_bit && h_bit <= word_weight) {
+ if (paint_switch)
+ word |= bit_masks[h_bit] << (word_weight - h_bit);
+ *cp++ = word;
+ /* "output" row(s) */
+ for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
+ *cp = *SUB(cp, bytes_wide);
+ ++cp;
+ }
+ rows_left -= PK_repeat_count + 1;
+ PK_repeat_count = 0;
+ word = 0;
+ word_weight = 32;
+ count -= h_bit;
+ h_bit = characterBitmaps[ch]->w;
+ } else {
+ if (paint_switch)
+ word |= bit_masks[word_weight];
+ *cp++ = word;
+ word = 0;
+ count -= word_weight;
+ h_bit -= word_weight;
+ word_weight = 32;
+ }
+ }
+ paint_switch = 1 - paint_switch;
+ }
+ if (cp != ((Q_UINT32 *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
+ oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(parent->filename));
+ if (rows_left != 0 || h_bit != characterBitmaps[ch]->w)
+ oops(i18n("Bad pk file (%1), too many bits").arg(parent->filename));
+ }
+
+ // The data in the bitmap is now in the processor's bit order,
+ // that is, big endian. Since XWindows needs little endian, we
+ // need to change the bit order now.
+ register unsigned char* bitmapData = (unsigned char*) characterBitmaps[ch]->bits;
+ register unsigned char* endOfData = bitmapData + characterBitmaps[ch]->bytes_wide*characterBitmaps[ch]->h;
+ while(bitmapData < endOfData) {
+ *bitmapData = bitflip[*bitmapData];
+ bitmapData++;
+ }
+
+ } else {
+
+ // Routines for small Endian start here. This applies e.g. to
+ // Intel and Alpha processors.
+
+#ifdef DEBUG_PK
+ kdDebug(4300) << "small Endian byte ordering" << endl;
+#endif
+
+ if (PK_dyn_f == 14) { /* get raster by bits */
+ memset(characterBitmaps[ch]->bits, 0, (int) characterBitmaps[ch]->h * bytes_wide);
+ for (i = 0; i < (int) characterBitmaps[ch]->h; i++) { /* get all rows */
+ cp = ADD(characterBitmaps[ch]->bits, i * bytes_wide);
+ row_bit_pos = -1;
+ for (j = 0; j < (int) characterBitmaps[ch]->w; j++) { /* get one row */
+ if (--PK_bitpos < 0) {
+ word = one(fp);
+ PK_bitpos = 7;
+ }
+ if (++row_bit_pos >= 32) {
+ cp++;
+ row_bit_pos = 0;
+ }
+ if (word & (1 << PK_bitpos))
+ *cp |= 1 << row_bit_pos;
+ }
+ }
+ } else { /* get packed raster */
+ rows_left = characterBitmaps[ch]->h;
+ h_bit = characterBitmaps[ch]->w;
+ PK_repeat_count = 0;
+ word_weight = 32;
+ word = 0;
+ while (rows_left > 0) {
+ count = PK_packed_num(fp);
+ while (count > 0) {
+ if (count < word_weight && count < h_bit) {
+ if (paint_switch)
+ word |= bit_masks[count] << (32 - word_weight);
+ h_bit -= count;
+ word_weight -= count;
+ count = 0;
+ } else
+ if (count >= h_bit && h_bit <= word_weight) {
+ if (paint_switch)
+ word |= bit_masks[h_bit] << (32 - word_weight);
+ *cp++ = word;
+ /* "output" row(s) */
+ for (i = PK_repeat_count * bytes_wide / 4; i > 0; --i) {
+ *cp = *SUB(cp, bytes_wide);
+ ++cp;
+ }
+ rows_left -= PK_repeat_count + 1;
+ PK_repeat_count = 0;
+ word = 0;
+ word_weight = 32;
+ count -= h_bit;
+ h_bit = characterBitmaps[ch]->w;
+ } else {
+ if (paint_switch)
+ word |= bit_masks[word_weight] << (32 - word_weight);
+ *cp++ = word;
+ word = 0;
+ count -= word_weight;
+ h_bit -= word_weight;
+ word_weight = 32;
+ }
+ }
+ paint_switch = 1 - paint_switch;
+ }
+ if (cp != ((Q_UINT32 *) (characterBitmaps[ch]->bits + bytes_wide * characterBitmaps[ch]->h)))
+ oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(parent->filename));
+ if (rows_left != 0 || h_bit != characterBitmaps[ch]->w)
+ oops(i18n("Bad pk file (%1), too many bits").arg(parent->filename));
+ }
+ } // endif: big or small Endian?
+}
+
+
+void TeXFont_PK::read_PK_index()
+{
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::read_PK_index() called" << endl;
+#endif
+
+ if (file == 0) {
+ kdError(4300) << "TeXFont_PK::read_PK_index(): file == 0" << endl;
+ return;
+ }
+
+ int magic = two(file);
+ if (magic != PK_MAGIC) {
+ kdError(4300) << "TeXFont_PK::read_PK_index(): file is not a PK file" << endl;
+ return;
+ }
+
+ fseek(file, (long) one(file), SEEK_CUR); /* skip comment */
+ (void) four(file); /* skip design size */
+
+ checksum = four(file);
+
+ int hppp = sfour(file);
+ int vppp = sfour(file);
+ if (hppp != vppp)
+ kdWarning(4300) << i18n("Font has non-square aspect ratio ") << vppp << ":" << hppp << endl;
+
+ // Read glyph directory (really a whole pass over the file).
+ for (;;) {
+ int bytes_left, flag_low_bits;
+ unsigned int ch;
+
+ PK_skip_specials();
+ if (PK_flag_byte == PK_POST)
+ break;
+ flag_low_bits = PK_flag_byte & 0x7;
+ if (flag_low_bits == 7) {
+ bytes_left = four(file);
+ ch = four(file);
+ } else
+ if (flag_low_bits > 3) {
+ bytes_left = ((flag_low_bits - 4) << 16) + two(file);
+ ch = one(file);
+ } else {
+ bytes_left = (flag_low_bits << 8) + one(file);
+ ch = one(file);
+ }
+
+ glyphtable[ch].addr = ftell(file);
+ glyphtable[ch].x2 = PK_flag_byte;
+ fseek(file, (long) bytes_left, SEEK_CUR);
+#ifdef DEBUG_PK
+ kdDebug(4300) << "Scanning pk char " << ch << "at " << glyphtable[ch].addr << endl;
+#endif
+ }
+#ifdef DEBUG_PK
+ kdDebug(4300) << "TeXFont_PK::read_PK_index() called" << endl;
+#endif
+}