KD Reports API Documentation  2.0
KDReportsFontScaler.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Reports library.
4 **
5 ** SPDX-FileCopyrightText: 2007-2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDAB-KDReports OR LicenseRef-KDAB-KDReports-US
8 **
9 ** Licensees holding valid commercial KD Reports licenses may use this file in
10 ** accordance with the KD Reports Commercial License Agreement provided with
11 ** the Software.
12 **
13 ** Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 **
15 ****************************************************************************/
16 
17 #include "KDReportsFontScaler_p.h"
18 #include <QDebug>
19 #include <QFont>
20 #include <QFontMetricsF>
21 
22 using namespace KDReports;
23 
24 FontScaler::FontScaler(const QFont &initialFont)
25  : m_font(initialFont)
26  , m_fontMetrics(m_font)
27  , m_initialFontMetrics(m_fontMetrics)
28  , m_scalingFactor(1.0)
29 {
30 }
31 
32 void FontScaler::setFontAndScalingFactor(const QFont &font, qreal scalingFactor)
33 {
34 #ifdef DEBUG_LAYOUT
35  // qDebug() << "setFontAndScalingFactor scalingFactor=" << scalingFactor;
36 #endif
37  m_font = font;
38  m_scalingFactor = scalingFactor;
39  if (m_font.pixelSize() == -1)
40  m_font.setPointSizeF(m_font.pointSizeF() * scalingFactor);
41  else
42  m_font.setPixelSize(qRound(m_font.pixelSize() * scalingFactor));
43  m_fontMetrics = QFontMetricsF(m_font);
44  m_initialFontMetrics = m_fontMetrics;
45 }
46 
48 {
49  // TODO this should be calculated in the end, using finalWidth/initialWidth. It's currently messed up by the -0.1 below for instance.
50  m_scalingFactor *= factor;
51 
52  if (m_font.pixelSize() == -1) {
53  if (factor > 0.99 && factor < 1.000) // applying 0.999 forever can take a very long time ;)
54  m_font.setPointSizeF(m_font.pointSizeF() - 0.1);
55  else
56  m_font.setPointSizeF(m_font.pointSizeF() * factor);
57  } else {
58  if (m_font.pixelSize() > 2 && factor > 0.99 && factor < 1.000)
59  m_font.setPixelSize(m_font.pixelSize() - 1);
60  else
61  m_font.setPixelSize(int(m_font.pixelSize() * factor));
62  }
63 #ifdef DEBUG_LAYOUT
64  qDebug() << " applyAdditionalScalingFactor" << factor << "combined factor:" << m_scalingFactor << "pointSize:" << m_font.pointSizeF() << "pixelSize:" << m_font.pixelSize();
65 #endif
66  m_fontMetrics = QFontMetricsF(m_font);
67 }
68 
69 static qreal textWidthForMetrics(const QFontMetricsF &fm, const QString &text)
70 {
71 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
72  return fm.width(text);
73 #else
74  return fm.size(Qt::TextSingleLine, text).width();
75 #endif
76 }
77 
78 qreal FontScaler::textWidth(const QString &text) const
79 {
80  return textWidthForMetrics(m_fontMetrics, text);
81 }
82 
83 void FontScaler::setFactorForHeight(qreal wantedHeight)
84 {
85 #ifdef DEBUG_LAYOUT
86  qDebug() << " FontScaler::setFactorForHeight" << wantedHeight;
87 #endif
88  Q_ASSERT(wantedHeight > 0);
89  qreal height = m_fontMetrics.height();
90  int iterations = 0;
91 
92  while (height > wantedHeight && height > 3.0 /* seems to be the min we can get */) {
93  const qreal factor = wantedHeight / height;
95  qreal prevHeight = height;
96  height = m_fontMetrics.height();
97 #ifdef DEBUG_LAYOUT
98  qDebug() << " FontScaler: height=" << height << factor << m_scalingFactor;
99 #endif
100  if (++iterations > 10 && height == prevHeight) {
101  // We're not getting anywhere, probably we're hitting a minimum width when
102  // trying to use a very, very small font (see unittest testFontScalerVerySmall)
103  break;
104  }
105  if (m_font.pixelSize() == 1) {
106  break;
107  }
108  }
109 }
110 
111 void FontScaler::setFactorForWidth(qreal wantedFactor, const QString &sampleText)
112 {
113 #ifdef DEBUG_LAYOUT
114  qDebug() << " FontScaler::setFactorForWidth" << wantedFactor;
115 #endif
116  // Just applying that scaling factor for the font size isn't enough,
117  // fonts do not scale proportionnally. We need do this like
118  // "scale the font so that this text fits into this width"
119  const qreal initialWidth = textWidthForMetrics(m_initialFontMetrics, sampleText);
120  const qreal wantedWidth = initialWidth * wantedFactor;
121  qreal width = textWidth(sampleText);
122 #ifdef DEBUG_LAYOUT
123  qDebug() << " FontScaler: sampleText with initialFontMetrics:" << initialWidth << "with current fontMetrics:" << width << "wanted:" << wantedWidth;
124 #endif
125 
126  int iterations = 0;
127 
128  while (width > wantedWidth) {
129  qreal factor = wantedWidth / width;
131  qreal prevWidth = width;
132  width = textWidth(sampleText);
133 #ifdef DEBUG_LAYOUT
134  qDebug() << " FontScaler: width=" << width << "factor=" << factor << "m_scalingFactor=" << m_scalingFactor;
135 #endif
136  if (++iterations > 10 && width == prevWidth) {
137  // We're not getting anywhere, probably we're hitting a minimum width when
138  // trying to use a very, very small font (see unittest testFontScalerVerySmall)
139  break;
140  }
141  }
142 }
KDReports::FontScaler::font
QFont font() const
Definition: KDReportsFontScaler_p.h:81
KDReports::FontScaler::FontScaler
FontScaler(const QFont &initialFont)
Definition: KDReportsFontScaler.cpp:24
KDReports::FontScaler::scalingFactor
qreal scalingFactor() const
Definition: KDReportsFontScaler_p.h:83
KDReports::FontScaler::setFactorForWidth
void setFactorForWidth(qreal wantedFactor, const QString &sampleText)
Definition: KDReportsFontScaler.cpp:111
KDReports::FontScaler::textWidth
qreal textWidth(const QString &text) const
Definition: KDReportsFontScaler.cpp:78
KDReports::FontScaler::setFactorForHeight
void setFactorForHeight(qreal wantedHeight)
Definition: KDReportsFontScaler.cpp:83
KDReportsFontScaler_p.h
KDReports::FontScaler::setFontAndScalingFactor
void setFontAndScalingFactor(const QFont &font, qreal scalingFactor)
Definition: KDReportsFontScaler.cpp:32
KDReports::FontScaler::applyAdditionalScalingFactor
void applyAdditionalScalingFactor(qreal factor)
Definition: KDReportsFontScaler.cpp:47
textWidthForMetrics
static qreal textWidthForMetrics(const QFontMetricsF &fm, const QString &text)
Definition: KDReportsFontScaler.cpp:69
KDReports
Definition: KDReportsAbstractReportLayout_p.h:30

© 2007-2021 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-reports/
Generated on Sat Jan 8 2022 02:38:32 for KD Reports API Documentation by doxygen 1.8.17