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 // TeXFont_TFM.cpp 0003 // 0004 // Part of KDVI - A DVI previewer for the KDE desktop environment 0005 // 0006 // SPDX-FileCopyrightText: 2003 Stefan Kebekus 0007 // SPDX-License-Identifier: GPL-2.0-or-later 0008 0009 #include <config.h> 0010 0011 #include "TeXFont_TFM.h" 0012 #include "debug_dvi.h" 0013 0014 #include <QDataStream> 0015 #include <QFile> 0016 #include <QLoggingCategory> 0017 0018 //#define DEBUG_TFM 0019 0020 TeXFont_TFM::TeXFont_TFM(TeXFontDefinition *parent) 0021 : TeXFont(parent) 0022 { 0023 #ifdef DEBUG_TFM 0024 qCDebug(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( parent=" << parent << " )"; 0025 #endif 0026 0027 QFile file(parent->filename); 0028 if (!file.open(QIODevice::ReadOnly)) { 0029 qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM(): Could not read TFM file"; 0030 return; 0031 } 0032 QDataStream stream(&file); 0033 0034 // Data from the very beginning of the TFM file, as specified in 0035 // "The DVI Driver Standard, Level 0", section D.2.1 0036 quint16 lf, lh, bc, ec, nw, nh, nd; 0037 stream >> lf >> lh >> bc >> ec >> nw >> nh >> nd; 0038 #ifdef DEBUG_TFM 0039 qCDebug(OkularDviDebug) << "lf= " << lf << "lh= " << lh << "\nbc= " << bc << "\nec= " << ec << "\nnw= " << nw << "\nnh= " << nh << "\nnd= " << nd; 0040 #endif 0041 if ((bc > ec) || (ec >= TeXFontDefinition::max_num_of_chars_in_font)) { 0042 qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid bc and ec entries."; 0043 file.close(); 0044 return; 0045 } 0046 0047 // Data from the HEADER section of the TFM data. 0048 file.seek(24); 0049 stream >> checksum >> design_size_in_TeX_points.value; 0050 #ifdef DEBUG_TFM 0051 qCDebug(OkularDviDebug) << "checksum = " << checksum << "design_size = " << design_size_in_TeX_points.toDouble() << " TeX Points\n" 0052 << " = " << design_size_in_TeX_points.toDouble() * 254.0 / 7227.0 << " cm"; 0053 #endif 0054 0055 // Width table 0056 fix_word widthTable_in_units_of_design_size[TeXFontDefinition::max_num_of_chars_in_font]; 0057 for (fix_word &fw : widthTable_in_units_of_design_size) { 0058 fw.value = 0; 0059 } 0060 0061 file.seek(24 + 4 * lh + 4 * (ec - bc)); 0062 for (unsigned int i = 0; i < nw; i++) { 0063 stream >> widthTable_in_units_of_design_size[i].value; 0064 // Some characters, which are used as parts of glyphs, have width 0065 // 0 --the real width is calculated in a lig_kern program and 0066 // depends on the preceding character. We cannot calculate the 0067 // real width here and take 0.4 times the design size as an 0068 // approximation. 0069 if (widthTable_in_units_of_design_size[i].value == 0) { 0070 widthTable_in_units_of_design_size[i].fromDouble(0.4); 0071 } 0072 } 0073 0074 // Height table 0075 fix_word heightTable_in_units_of_design_size[16]; 0076 for (fix_word &fw : heightTable_in_units_of_design_size) { 0077 fw.value = 0; 0078 } 0079 for (unsigned int i = 0; i < nh; i++) { 0080 stream >> heightTable_in_units_of_design_size[i].value; 0081 } 0082 0083 // Char-Info table 0084 file.seek(24 + 4 * lh); 0085 for (unsigned int characterCode = bc; characterCode < ec; characterCode++) { 0086 glyph *g = glyphtable + characterCode; 0087 0088 quint8 byte; 0089 stream >> byte; 0090 if (byte >= nw) { 0091 qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid Char-Info table."; 0092 } else { 0093 characterWidth_in_units_of_design_size[characterCode] = widthTable_in_units_of_design_size[byte]; 0094 g->dvi_advance_in_units_of_design_size_by_2e20 = widthTable_in_units_of_design_size[byte].value; 0095 } 0096 0097 stream >> byte; 0098 byte = byte >> 4; 0099 if (byte >= nh) { 0100 qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid Char-Info table."; 0101 } else { 0102 characterHeight_in_units_of_design_size[characterCode] = heightTable_in_units_of_design_size[byte]; 0103 } 0104 0105 stream >> byte; 0106 stream >> byte; 0107 } 0108 file.close(); 0109 } 0110 0111 TeXFont_TFM::~TeXFont_TFM() 0112 { 0113 } 0114 0115 glyph *TeXFont_TFM::getGlyph(quint16 characterCode, bool generateCharacterPixmap, const QColor &color) 0116 { 0117 #ifdef DEBUG_TFM 0118 qCDebug(OkularDviDebug) << "TeXFont_TFM::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )"; 0119 #endif 0120 0121 // Paranoia checks 0122 if (characterCode >= TeXFontDefinition::max_num_of_chars_in_font) { 0123 qCCritical(OkularDviDebug) << "TeXFont_TFM::getGlyph(): Argument is too big."; 0124 return glyphtable; 0125 } 0126 0127 // This is the address of the glyph that will be returned. 0128 class glyph *g = glyphtable + characterCode; 0129 0130 if ((generateCharacterPixmap == true) && ((g->shrunkenCharacter.isNull()) || (color != g->color))) { 0131 g->color = color; 0132 quint16 pixelWidth = (quint16)(parent->displayResolution_in_dpi * design_size_in_TeX_points.toDouble() * characterWidth_in_units_of_design_size[characterCode].toDouble() * 100.0 / 7227.0 + 0.5); 0133 quint16 pixelHeight = (quint16)(parent->displayResolution_in_dpi * design_size_in_TeX_points.toDouble() * characterHeight_in_units_of_design_size[characterCode].toDouble() * 100.0 / 7227.0 + 0.5); 0134 0135 // Just make sure that weird TFM files never lead to giant 0136 // pixmaps that eat all system memory... 0137 if (pixelWidth > 50) { 0138 pixelWidth = 50; 0139 } 0140 if (pixelHeight > 50) { 0141 pixelHeight = 50; 0142 } 0143 0144 g->shrunkenCharacter = QImage(pixelWidth, pixelHeight, QImage::Format_RGB32); 0145 g->shrunkenCharacter.fill(color.rgba()); 0146 g->x2 = 0; 0147 g->y2 = pixelHeight; 0148 } 0149 0150 return g; 0151 }