summaryrefslogtreecommitdiff
path: root/dviware/dvisvgm/src/DVIReader.cpp
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-01-12 03:01:29 +0000
committerNorbert Preining <norbert@preining.info>2023-01-12 03:01:29 +0000
commit6a7900c93acc16d1bbd2f1e26286c7dd7387e6c0 (patch)
tree76196287351cba68a51934c49468bf1a7846aa76 /dviware/dvisvgm/src/DVIReader.cpp
parentc1c19023b4b1d43cb874f84df5102b485853e672 (diff)
CTAN sync 202301120301
Diffstat (limited to 'dviware/dvisvgm/src/DVIReader.cpp')
-rw-r--r--dviware/dvisvgm/src/DVIReader.cpp49
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);
}