You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
5.5 KiB
144 lines
5.5 KiB
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*- |
|
// TeXFont_TFM.cpp |
|
// |
|
// Part of KDVI - A DVI previewer for the KDE desktop environment |
|
// |
|
// (C) 2003 Stefan Kebekus |
|
// Distributed under the GPL |
|
|
|
#include <config.h> |
|
|
|
#include "TeXFont_TFM.h" |
|
#include "debug_dvi.h" |
|
|
|
#include <QDataStream> |
|
#include <QFile> |
|
#include <QLoggingCategory> |
|
|
|
//#define DEBUG_TFM |
|
|
|
TeXFont_TFM::TeXFont_TFM(TeXFontDefinition *parent) |
|
: TeXFont(parent) |
|
{ |
|
#ifdef DEBUG_TFM |
|
qCDebug(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( parent=" << parent << " )"; |
|
#endif |
|
|
|
QFile file(parent->filename); |
|
if (!file.open(QIODevice::ReadOnly)) { |
|
qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM(): Could not read TFM file" << endl; |
|
return; |
|
} |
|
QDataStream stream(&file); |
|
|
|
// Data from the very beginning of the TFM file, as specified in |
|
// "The DVI Driver Standard, Level 0", section D.2.1 |
|
quint16 lf, lh, bc, ec, nw, nh, nd; |
|
stream >> lf >> lh >> bc >> ec >> nw >> nh >> nd; |
|
#ifdef DEBUG_TFM |
|
qCDebug(OkularDviDebug) << "lf= " << lf << "lh= " << lh << endl << "bc= " << bc << endl << "ec= " << ec << endl << "nw= " << nw << endl << "nh= " << nh << endl << "nd= " << nd << endl; |
|
#endif |
|
if ((bc > ec) || (ec >= TeXFontDefinition::max_num_of_chars_in_font)) { |
|
qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid bc and ec entries." << endl; |
|
file.close(); |
|
return; |
|
} |
|
|
|
// Data from the HEADER section of the TFM data. |
|
file.seek(24); |
|
stream >> checksum >> design_size_in_TeX_points.value; |
|
#ifdef DEBUG_TFM |
|
qCDebug(OkularDviDebug) << "checksum = " << checksum << "design_size = " << design_size_in_TeX_points.toDouble() << " TeX Points" << endl << " = " << design_size_in_TeX_points.toDouble() * 254.0 / 7227.0 << " cm" << endl; |
|
#endif |
|
|
|
// Width table |
|
fix_word widthTable_in_units_of_design_size[TeXFontDefinition::max_num_of_chars_in_font]; |
|
for (fix_word &fw : widthTable_in_units_of_design_size) |
|
fw.value = 0; |
|
|
|
file.seek(24 + 4 * lh + 4 * (ec - bc)); |
|
for (unsigned int i = 0; i < nw; i++) { |
|
stream >> widthTable_in_units_of_design_size[i].value; |
|
// Some characters, which are used as parts of glyphs, have width |
|
// 0 --the real width is calculated in a lig_kern program and |
|
// depends on the preceding character. We cannot calculate the |
|
// real width here and take 0.4 times the design size as an |
|
// approximation. |
|
if (widthTable_in_units_of_design_size[i].value == 0) |
|
widthTable_in_units_of_design_size[i].fromDouble(0.4); |
|
} |
|
|
|
// Height table |
|
fix_word heightTable_in_units_of_design_size[16]; |
|
for (fix_word &fw : heightTable_in_units_of_design_size) |
|
fw.value = 0; |
|
for (unsigned int i = 0; i < nh; i++) { |
|
stream >> heightTable_in_units_of_design_size[i].value; |
|
} |
|
|
|
// Char-Info table |
|
file.seek(24 + 4 * lh); |
|
for (unsigned int characterCode = bc; characterCode < ec; characterCode++) { |
|
glyph *g = glyphtable + characterCode; |
|
|
|
quint8 byte; |
|
stream >> byte; |
|
if (byte >= nw) |
|
qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid Char-Info table." << endl; |
|
else { |
|
characterWidth_in_units_of_design_size[characterCode] = widthTable_in_units_of_design_size[byte]; |
|
g->dvi_advance_in_units_of_design_size_by_2e20 = widthTable_in_units_of_design_size[byte].value; |
|
} |
|
|
|
stream >> byte; |
|
byte = byte >> 4; |
|
if (byte >= nh) |
|
qCCritical(OkularDviDebug) << "TeXFont_TFM::TeXFont_TFM( filename=" << parent->filename << " ): The font has an invalid Char-Info table." << endl; |
|
else |
|
characterHeight_in_units_of_design_size[characterCode] = heightTable_in_units_of_design_size[byte]; |
|
|
|
stream >> byte; |
|
stream >> byte; |
|
} |
|
file.close(); |
|
} |
|
|
|
TeXFont_TFM::~TeXFont_TFM() |
|
{ |
|
} |
|
|
|
glyph *TeXFont_TFM::getGlyph(quint16 characterCode, bool generateCharacterPixmap, const QColor &color) |
|
{ |
|
#ifdef DEBUG_TFM |
|
qCDebug(OkularDviDebug) << "TeXFont_TFM::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )"; |
|
#endif |
|
|
|
// Paranoia checks |
|
if (characterCode >= TeXFontDefinition::max_num_of_chars_in_font) { |
|
qCCritical(OkularDviDebug) << "TeXFont_TFM::getGlyph(): Argument is too big." << endl; |
|
return glyphtable; |
|
} |
|
|
|
// This is the address of the glyph that will be returned. |
|
class glyph *g = glyphtable + characterCode; |
|
|
|
if ((generateCharacterPixmap == true) && ((g->shrunkenCharacter.isNull()) || (color != g->color))) { |
|
g->color = color; |
|
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); |
|
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); |
|
|
|
// Just make sure that weird TFM files never lead to giant |
|
// pixmaps that eat all system memory... |
|
if (pixelWidth > 50) |
|
pixelWidth = 50; |
|
if (pixelHeight > 50) |
|
pixelHeight = 50; |
|
|
|
g->shrunkenCharacter = QImage(pixelWidth, pixelHeight, QImage::Format_RGB32); |
|
g->shrunkenCharacter.fill(color.rgba()); |
|
g->x2 = 0; |
|
g->y2 = pixelHeight; |
|
} |
|
|
|
return g; |
|
}
|
|
|