File indexing completed on 2024-05-12 16:06:40

0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
0002 #include <config.h>
0003 
0004 #include "TeXFontDefinition.h"
0005 #include "debug_dvi.h"
0006 #include "dviRenderer.h"
0007 #ifdef HAVE_FREETYPE
0008 #include "TeXFont_PFB.h"
0009 #endif
0010 #include "TeXFont_PK.h"
0011 #include "TeXFont_TFM.h"
0012 #include "debug_dvi.h"
0013 #include "xdvi.h"
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <QFile>
0018 #include <QLoggingCategory>
0019 
0020 extern const int MFResolutions[];
0021 
0022 #define PK_PRE 247
0023 #define PK_ID 89
0024 #define PK_MAGIC (PK_PRE << 8) + PK_ID
0025 #define GF_PRE 247
0026 #define GF_ID 131
0027 #define GF_MAGIC (GF_PRE << 8) + GF_ID
0028 #define VF_PRE 247
0029 #define VF_ID_BYTE 202
0030 #define VF_MAGIC (VF_PRE << 8) + VF_ID_BYTE
0031 
0032 // #define DEBUG_FONT
0033 
0034 TeXFontDefinition::TeXFontDefinition(const QString &nfontname, double _displayResolution_in_dpi, quint32 chk, qint32 _scaled_size_in_DVI_units, class fontPool *pool, double _enlargement)
0035 {
0036 #ifdef DEBUG_FONT
0037     qCDebug(OkularDviDebug) << "TeXFontDefinition::TeXFontDefinition(...); fontname=" << nfontname << ", enlargement=" << _enlargement;
0038 #endif
0039 
0040     enlargement = _enlargement;
0041     font_pool = pool;
0042     fontname = nfontname;
0043     font = nullptr;
0044     displayResolution_in_dpi = _displayResolution_in_dpi;
0045     checksum = chk;
0046     flags = TeXFontDefinition::FONT_IN_USE;
0047     file = nullptr;
0048     filename.clear();
0049     scaled_size_in_DVI_units = _scaled_size_in_DVI_units;
0050 
0051     macrotable = nullptr;
0052 
0053     // By default, this font contains only empty characters. After the
0054     // font has been loaded, this function pointer will be replaced by
0055     // another one.
0056     set_char_p = &dviRenderer::set_empty_char;
0057 }
0058 
0059 TeXFontDefinition::~TeXFontDefinition()
0060 {
0061 #ifdef DEBUG_FONT
0062     qCDebug(OkularDviDebug) << "discarding font " << fontname << " at " << (int)(enlargement * MFResolutions[font_pool->getMetafontMode()] + 0.5) << " dpi";
0063 #endif
0064 
0065     if (font != nullptr) {
0066         delete font;
0067         font = nullptr;
0068     }
0069     if (macrotable != nullptr) {
0070         delete[] macrotable;
0071         macrotable = nullptr;
0072     }
0073 
0074     if (flags & FONT_LOADED) {
0075         if (file != nullptr) {
0076             fclose(file);
0077             file = nullptr;
0078         }
0079         if (flags & FONT_VIRTUAL) {
0080             vf_table.clear();
0081         }
0082     }
0083 }
0084 
0085 void TeXFontDefinition::fontNameReceiver(const QString &fname)
0086 {
0087 #ifdef DEBUG_FONT
0088     qCDebug(OkularDviDebug) << "void TeXFontDefinition::fontNameReceiver( " << fname << " )";
0089 #endif
0090 
0091     flags |= TeXFontDefinition::FONT_LOADED;
0092     filename = fname;
0093 #ifdef HAVE_FREETYPE
0094     fullFontName.clear();
0095     fullEncodingName.clear();
0096 #endif
0097 
0098     file = fopen(QFile::encodeName(filename).constData(), "r");
0099     // Check if the file could be opened. If not, try to find the file
0100     // in the DVI file's directory. If that works, modify the filename
0101     // accordingly and go on.
0102     if (file == nullptr) {
0103         QString filename_test(font_pool->getExtraSearchPath() + QLatin1Char('/') + filename);
0104         file = fopen(QFile::encodeName(filename_test).constData(), "r");
0105         if (file == nullptr) {
0106             qCCritical(OkularDviDebug) << i18n("Cannot find font %1, file %2.", fontname, filename);
0107             return;
0108         } else {
0109             filename = filename_test;
0110         }
0111     }
0112 
0113     set_char_p = &dviRenderer::set_char;
0114     int magic = two(file);
0115 
0116     if (fname.endsWith(QLatin1String("pk"))) {
0117         if (magic == PK_MAGIC) {
0118             fclose(file);
0119             file = nullptr;
0120             font = new TeXFont_PK(this);
0121             set_char_p = &dviRenderer::set_char;
0122             if ((checksum != 0) && (checksum != font->checksum)) {
0123                 qCWarning(OkularDviDebug) << i18n("Checksum mismatch for font file %1", filename);
0124             }
0125             fontType = TEX_PK;
0126             return;
0127         }
0128     }
0129 
0130     if (fname.endsWith(QLatin1String(".vf"))) {
0131         if (magic == VF_MAGIC) {
0132             read_VF_index();
0133             set_char_p = &dviRenderer::set_vf_char;
0134             fontType = TEX_VIRTUAL;
0135             return;
0136         }
0137     }
0138 
0139     if (fname.endsWith(QLatin1String(".tfm"))) {
0140         fclose(file);
0141         file = nullptr;
0142         font = new TeXFont_TFM(this);
0143         set_char_p = &dviRenderer::set_char;
0144         fontType = TEX_FONTMETRIC;
0145         return;
0146     }
0147 
0148     // None of these known types? Then it should be one of the font
0149     // formats that are handled by the FreeType library
0150     fclose(file);
0151     file = nullptr;
0152 #ifdef HAVE_FREETYPE
0153     // Find the encoding for that font
0154     const QString &enc = font_pool->fontsByTeXName.findEncoding(fontname);
0155 
0156     if (enc.isEmpty() == false) {
0157 #ifdef DEBUG_FONT
0158         qCDebug(OkularDviDebug) << "Font " << fontname << " uses encoding " << enc;
0159 #endif
0160         font = new TeXFont_PFB(this, font_pool->encodingPool.findByName(enc), font_pool->fontsByTeXName.findSlant(fontname));
0161     } else {
0162 #ifdef DEBUG_FONT
0163         qCDebug(OkularDviDebug) << "Font " << fontname << " does not have an encoding.";
0164 #endif
0165         font = new TeXFont_PFB(this);
0166     }
0167 
0168     set_char_p = &dviRenderer::set_char;
0169     fontType = FREETYPE;
0170     return;
0171 #else
0172     // If we don't have the FreeType library, we should never have
0173     // reached this point. Complain, and leave this font blank
0174     qCCritical(OkularDviDebug) << i18n("Cannot recognize format for font file %1", filename);
0175 #endif
0176 }
0177 
0178 void TeXFontDefinition::reset()
0179 {
0180     if (font != nullptr) {
0181         delete font;
0182         font = nullptr;
0183     }
0184 
0185     if (macrotable != nullptr) {
0186         delete[] macrotable;
0187         macrotable = nullptr;
0188     }
0189 
0190     if (flags & FONT_LOADED) {
0191         if (file != nullptr) {
0192             fclose(file);
0193             file = nullptr;
0194         }
0195         if (flags & FONT_VIRTUAL) {
0196             vf_table.clear();
0197         }
0198     }
0199 
0200     filename.clear();
0201     flags = TeXFontDefinition::FONT_IN_USE;
0202     set_char_p = &dviRenderer::set_empty_char;
0203 }
0204 
0205 void TeXFontDefinition::setDisplayResolution(double _displayResolution_in_dpi)
0206 {
0207     displayResolution_in_dpi = _displayResolution_in_dpi;
0208     if (font != nullptr) {
0209         font->setDisplayResolution();
0210     }
0211 }
0212 
0213 /** mark_as_used marks the font, and all the fonts it refers to, as
0214     used, i.e. their FONT_IN_USE-flag is set. */
0215 
0216 void TeXFontDefinition::mark_as_used()
0217 {
0218 #ifdef DEBUG_FONT
0219     qCDebug(OkularDviDebug) << "TeXFontDefinition::mark_as_used()";
0220 #endif
0221 
0222     if (flags & TeXFontDefinition::FONT_IN_USE) {
0223         return;
0224     }
0225 
0226     flags |= TeXFontDefinition::FONT_IN_USE;
0227 
0228     // For virtual fonts, also go through the list of referred fonts
0229     if (flags & TeXFontDefinition::FONT_VIRTUAL) {
0230         QHashIterator<int, TeXFontDefinition *> it(vf_table);
0231         while (it.hasNext()) {
0232             it.next();
0233             it.value()->flags |= TeXFontDefinition::FONT_IN_USE;
0234         }
0235     }
0236 }
0237 
0238 macro::macro()
0239 {
0240     pos = nullptr;                                   /* address of first byte of macro */
0241     end = nullptr;                                   /* address of last+1 byte */
0242     dvi_advance_in_units_of_design_size_by_2e20 = 0; /* DVI units to move reference point */
0243     free_me = false;
0244 }
0245 
0246 macro::~macro()
0247 {
0248     if ((pos != nullptr) && (free_me == true)) {
0249         delete[] pos;
0250     }
0251 }