Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsvgfont.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsvgfont_p.h"
5
6#include "qpainter.h"
7#include "qpen.h"
8#include "qdebug.h"
9#include "qpicture.h"
10
12
13QSvgGlyph::QSvgGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX)
14 : m_unicode(unicode), m_path(path), m_horizAdvX(horizAdvX)
15{
16
17}
18
19
20QSvgFont::QSvgFont(qreal horizAdvX)
21 : m_horizAdvX(horizAdvX)
22{
23}
24
25
26QString QSvgFont::familyName() const
27{
28 return m_familyName;
29}
30
31
32void QSvgFont::addGlyph(QChar unicode, const QPainterPath &path, qreal horizAdvX )
33{
34 m_glyphs.insert(unicode, QSvgGlyph(unicode, path,
35 (horizAdvX==-1)?m_horizAdvX:horizAdvX));
36}
37
38bool QSvgFont::addMissingGlyph(const QPainterPath &path, qreal horizAdvX)
39{
40 if (m_missingGlyph) {
41 qWarning("The font already has a 'missing-glyph' element.");
42 return false;
43 }
44 m_missingGlyph.reset(new QSvgGlyph(QChar(), path, (horizAdvX == -1) ? m_horizAdvX : horizAdvX));
45 return true;
46}
47
48
49void QSvgFont::draw(QPainter *p, const QPointF &point, const QString &str,
50 qreal pixelSize, Qt::Alignment alignment) const
51{
52 draw_helper(p, point, str, pixelSize, alignment, nullptr);
53}
54
55QRectF QSvgFont::boundingRect(QPainter *p, const QPointF &point, const QString &str,
56 qreal pixelSize, Qt::Alignment alignment) const
57{
58 QRectF bounds;
59 draw_helper(p, point, str, pixelSize, alignment, &bounds);
60 return bounds;
61}
62
63void QSvgFont::draw_helper(QPainter *p, const QPointF &point, const QString &str, qreal pixelSize,
64 Qt::Alignment alignment, QRectF *boundingRect) const
65{
66 const bool isPainting = (boundingRect == nullptr);
67
68 p->save();
69 p->translate(point);
70 p->scale(pixelSize / m_unitsPerEm, -pixelSize / m_unitsPerEm);
71
72 // Calculate the text width to be used for alignment
73 int textWidth = 0;
74 QString::const_iterator itr = str.constBegin();
75 for ( ; itr != str.constEnd(); ++itr) {
76 QChar unicode = *itr;
77 if (!m_glyphs.contains(*itr)) {
78 if (m_missingGlyph)
79 textWidth += static_cast<int>(m_missingGlyph->m_horizAdvX);
80 continue;
81 }
82 textWidth += static_cast<int>(m_glyphs[unicode].m_horizAdvX);
83 }
84
85 QPoint alignmentOffset(0, 0);
86 if (alignment == Qt::AlignHCenter) {
87 alignmentOffset.setX(-textWidth / 2);
88 } else if (alignment == Qt::AlignRight) {
89 alignmentOffset.setX(-textWidth);
90 }
91
92 p->translate(alignmentOffset);
93
94 // since in SVG the embedded font ain't really a path
95 // the outline has got to stay untransformed...
96 qreal penWidth = p->pen().widthF();
97 penWidth /= (pixelSize/m_unitsPerEm);
98 QPen pen = p->pen();
99 pen.setWidthF(penWidth);
100 p->setPen(pen);
101
102 itr = str.constBegin();
103 for ( ; itr != str.constEnd(); ++itr) {
104 QSvgGlyph foundGlyph;
105 QChar unicode = *itr;
106 if (m_glyphs.contains(*itr)) {
107 foundGlyph = m_glyphs[unicode];
108 } else {
109 if (!m_missingGlyph)
110 continue;
111 foundGlyph = *m_missingGlyph;
112 }
113
114 if (isPainting)
115 p->drawPath(foundGlyph.m_path);
116
117 if (boundingRect) {
118 QPainterPathStroker stroker;
119 stroker.setWidth(penWidth);
120 stroker.setJoinStyle(p->pen().joinStyle());
121 stroker.setMiterLimit(p->pen().miterLimit());
122 QPainterPath stroke = stroker.createStroke(foundGlyph.m_path);
123 *boundingRect |= p->transform().map(stroke).boundingRect();
124 }
125
126 p->translate(foundGlyph.m_horizAdvX, 0);
127 }
128
129 p->restore();
130}
131
132void QSvgFont::setFamilyName(const QString &name)
133{
134 m_familyName = name;
135}
136
137void QSvgFont::setUnitsPerEm(qreal upem)
138{
139 m_unitsPerEm = upem;
140}
141
142QT_END_NAMESPACE