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

© 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 by doxygen 1.9.1