File indexing completed on 2024-05-12 04:34:00

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 
0008 #include <config.h>
0009 
0010 #include "debug_dvi.h"
0011 #include "dvi.h"
0012 #include "dviRenderer.h"
0013 #include "xdvi.h"
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <cstdlib>
0018 #include <cstring>
0019 
0020 extern void oops(const QString &message);
0021 
0022 /***
0023  ***   VF font reading routines.
0024  ***   Public routine is read_index---because virtual characters are presumed
0025  ***   to be short, we read the whole virtual font in at once, instead of
0026  ***   faulting in characters as needed.
0027  ***/
0028 
0029 #define LONG_CHAR 242
0030 
0031 /*
0032  *  These are parameters which determine whether macros are combined for
0033  *  storage allocation purposes.  Small macros ( <= VF_PARM_1 bytes) are
0034  *  combined into chunks of size VF_PARM_2.
0035  */
0036 
0037 #ifndef VF_PARM_1
0038 #define VF_PARM_1 20
0039 #endif
0040 #ifndef VF_PARM_2
0041 #define VF_PARM_2 256
0042 #endif
0043 
0044 /*
0045  *  The main routine
0046  */
0047 
0048 void TeXFontDefinition::read_VF_index()
0049 {
0050 #ifdef DEBUG_FONTS
0051     qCDebug(OkularDviDebug) << "font::read_VF_index()";
0052 #endif
0053     FILE *VF_file = file;
0054     unsigned char cmnd;
0055     // available space for macros
0056     unsigned char *avail, *availend;
0057 
0058     flags |= FONT_VIRTUAL;
0059     set_char_p = &dviRenderer::set_vf_char;
0060 #ifdef DEBUG_FONTS
0061     qCDebug(OkularDviDebug) << "TeXFontDefinition::read_VF_index: reading VF pixel file " << filename;
0062 #endif
0063     // Read preamble.
0064     fseek(VF_file, (long)one(VF_file), 1); /* skip comment */
0065     quint32 const file_checksum = four(VF_file);
0066 
0067     if (file_checksum && checksum && file_checksum != checksum) {
0068         qCCritical(OkularDviDebug) << "Checksum mismatch dvi = " << checksum << "u, vf = " << file_checksum << "u) in font file" << filename;
0069     }
0070     (void)four(VF_file); /* skip design size */
0071 
0072     // Read the fonts.
0073     first_font = nullptr;
0074     while ((cmnd = one(VF_file)) >= FNTDEF1 && cmnd <= FNTDEF4) {
0075         int TeXnumber = num(VF_file, (int)cmnd - FNTDEF1 + 1);
0076         quint32 checksum = four(VF_file);
0077         quint32 scale = four(VF_file);
0078         quint32 design = four(VF_file);
0079         Q_UNUSED(design);
0080         quint16 len = one(VF_file) + one(VF_file); /* sequence point in the middle */
0081         char *fontname = new char[len + 1];
0082         fread(fontname, sizeof(char), len, VF_file);
0083         fontname[len] = '\0';
0084 
0085 #ifdef DEBUG_FONTS
0086         qCDebug(OkularDviDebug) << "Virtual font defines subfont \"" << fontname << "\" scale=" << scale << " design=" << design;
0087 #endif
0088 
0089         // According to Knuth's documentation found in the web source code
0090         // of the "vftovp" program (which seems to be the standard
0091         // definition of virtual fonts), the "scale" is a fixed point
0092         // number which describes extra enlargement that the virtual font
0093         // imposes. One obtains the enlargement by dividing 2^20.
0094         double enlargement_factor = double(scale) / (1 << 20) * enlargement;
0095 
0096         //    TeXFontDefinition *newfontp = font_pool->appendx(fontname, checksum, (quint32)(scaled_size_in_DVI_units*enlargement_factor), enlargement_factor);
0097         TeXFontDefinition *newfontp = font_pool->appendx(QString::fromLocal8Bit(fontname), checksum, (quint32)((double(scale) / (1 << 20)) * scaled_size_in_DVI_units), enlargement_factor);
0098 
0099         // Insert font in dictionary and make sure the dictionary is big
0100         // enough.
0101         if (vf_table.capacity() - 2 <= vf_table.count()) {
0102             // Not quite optimal. The size of the dictionary should be a
0103             // prime. I don't care.
0104             vf_table.reserve(vf_table.capacity() * 2);
0105         }
0106         vf_table.insert(TeXnumber, newfontp);
0107 
0108         if (first_font == nullptr) {
0109             first_font = newfontp;
0110         }
0111     }
0112 
0113     // Prepare macro array.
0114     macrotable = new macro[max_num_of_chars_in_font];
0115     if (macrotable == nullptr) {
0116         qCCritical(OkularDviDebug) << "Could not allocate memory for a macro table.";
0117         exit(0);
0118     }
0119 
0120     // Read macros.
0121     avail = availend = nullptr;
0122     for (; cmnd <= LONG_CHAR; cmnd = one(VF_file)) {
0123         macro *m;
0124         int len;
0125         unsigned long cc;
0126         long width;
0127 
0128         if (cmnd == LONG_CHAR) { /* long form packet */
0129             len = four(VF_file);
0130             cc = four(VF_file);
0131             width = four(VF_file);
0132             if (cc >= 256) {
0133                 qCCritical(OkularDviDebug) << "Virtual character" << cc << "in font" << fontname << "ignored.";
0134                 fseek(VF_file, (long)len, 1);
0135                 continue;
0136             }
0137         } else { /* short form packet */
0138             len = cmnd;
0139             cc = one(VF_file);
0140             width = num(VF_file, 3);
0141         }
0142         m = &macrotable[cc];
0143 
0144         m->dvi_advance_in_units_of_design_size_by_2e20 = width;
0145         if (len > 0) {
0146             if (len <= availend - avail) {
0147                 m->pos = avail;
0148                 avail += len;
0149             } else {
0150                 m->free_me = true;
0151                 if (len <= VF_PARM_1) {
0152                     m->pos = avail = new unsigned char[VF_PARM_2];
0153                     availend = avail + VF_PARM_2;
0154                     avail += len;
0155                 } else {
0156                     m->pos = new unsigned char[len];
0157                 }
0158             }
0159             fread((char *)m->pos, 1, len, VF_file);
0160             m->end = m->pos + len;
0161         }
0162     }
0163     if (cmnd != POST) {
0164         oops(i18n("Wrong command byte found in VF macro list: %1", cmnd));
0165     }
0166 
0167     fclose(VF_file);
0168     file = nullptr;
0169 }