diff options
author | Norbert Preining <norbert@preining.info> | 2023-01-12 03:01:29 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-01-12 03:01:29 +0000 |
commit | 6a7900c93acc16d1bbd2f1e26286c7dd7387e6c0 (patch) | |
tree | 76196287351cba68a51934c49468bf1a7846aa76 /dviware/dvisvgm/src/DVIReader.cpp | |
parent | c1c19023b4b1d43cb874f84df5102b485853e672 (diff) |
CTAN sync 202301120301
Diffstat (limited to 'dviware/dvisvgm/src/DVIReader.cpp')
-rw-r--r-- | dviware/dvisvgm/src/DVIReader.cpp | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/dviware/dvisvgm/src/DVIReader.cpp b/dviware/dvisvgm/src/DVIReader.cpp index b8c5bc449e..6dd7bebb69 100644 --- a/dviware/dvisvgm/src/DVIReader.cpp +++ b/dviware/dvisvgm/src/DVIReader.cpp @@ -2,7 +2,7 @@ ** DVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2022 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2023 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -595,6 +595,20 @@ void DVIReader::cmdXFontDef (int) { } +/** Returns the width of a string typed with a given font. + * @param[in] glyphs glyphs of the string + * @param[in] font assigned font + * @return width in bp units */ +static double string_width (const vector<uint16_t> &glyphs, const Font *font) { + double width=0; + if (auto nfont = font_cast<const NativeFont*>(font)) { + for (auto glyph: glyphs) + width += nfont->hAdvance(Character(Character::INDEX, glyph)); + } + return width; +} + + /** XDV extension: prints an array of characters where each character * can take independent x and y coordinates. * parameters: w[4] n[2] (dx,dy)[(4+4)n] glyphs[2n] */ @@ -602,11 +616,14 @@ void DVIReader::cmdXGlyphArray (int) { vector<double> dx, dy; vector<uint16_t> glyphs; double width = putGlyphArray(false, dx, dy, glyphs); - if (Font *font = FontManager::instance().getFont(_currFontNum)) - dviXGlyphArray(dx, dy, glyphs, *font); - else + Font *font = FontManager::instance().getFont(_currFontNum); + if (!font) throw DVIException("missing setfont prior to xglypharray"); - moveRight(width, MoveMode::SETCHAR); + dviXGlyphArray(dx, dy, glyphs, *font); + double diff = abs(string_width(glyphs, font) - width); + // if the given width differs from the actual width of the string, + // we must force a position change to prevent misalignments + moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } @@ -617,11 +634,14 @@ void DVIReader::cmdXGlyphString (int) { vector<double> dx, dy; vector<uint16_t> glyphs; double width = putGlyphArray(true, dx, dy, glyphs); - if (Font *font = FontManager::instance().getFont(_currFontNum)) - dviXGlyphString(dx, glyphs, *font); - else + Font *font = FontManager::instance().getFont(_currFontNum); + if (!font) throw DVIException("missing setfont prior to xglyphstring"); - moveRight(width, MoveMode::SETCHAR); + dviXGlyphString(dx, glyphs, *font); + double diff = abs(string_width(glyphs, font) - width); + // if the given width differs from the actual width of the string, + // we must force a position change to prevent misalignments + moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } @@ -639,11 +659,14 @@ void DVIReader::cmdXTextAndGlyphs (int) { vector<double> x, y; vector<uint16_t> glyphs; double width = putGlyphArray(false, x, y, glyphs); - if (Font *font = FontManager::instance().getFont(_currFontNum)) - dviXTextAndGlyphs(x, y, chars, glyphs, *font); - else + Font *font = FontManager::instance().getFont(_currFontNum); + if (!font) throw DVIException("missing setfont prior to xtextandglyphs"); - moveRight(width, MoveMode::SETCHAR); + dviXTextAndGlyphs(x, y, chars, glyphs, *font); + double diff = abs(string_width(glyphs, font) - width); + // if the given width differs from the actual width of the string, + // we must force a position change to prevent misalignments + moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } |