1 /*
2  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB.  All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "KChartTextAttributes.h"
21 
22 #include <KChartCartesianCoordinatePlane.h>
23 #include <KChartCartesianCoordinatePlane_p.h>
24 #include "KChartMath_p.h"
25 
26 #include <QFont>
27 #include <QPen>
28 #include <qglobal.h>
29 #include <QApplication>
30 #include <QSharedPointer>
31 #include <QTextDocument>
32 
33 #define d d_func()
34 
35 using namespace KChart;
36 
37 class Q_DECL_HIDDEN TextAttributes::Private
38 {
39     friend class TextAttributes;
40 public:
41      Private();
42 private:
43     bool visible;
44     QFont font;
45     mutable QFont cachedFont;
46     mutable qreal cachedFontSize;
47     Measure fontSize;
48     Measure minimalFontSize;
49     bool autoRotate;
50     bool autoShrink;
51     bool hasRotation;
52     int rotation;
53     QPen pen;
54     QSharedPointer<QTextDocument> document;
55 };
56 
Private()57 TextAttributes::Private::Private()
58     : visible( true ),
59       font( QApplication::font() ),
60       cachedFontSize( -1.0 ),
61       autoRotate( false ),
62       autoShrink( false ),
63       hasRotation( false ),
64       rotation( 0 ),
65       pen( Qt::black )
66 {
67 }
68 
TextAttributes()69 TextAttributes::TextAttributes()
70     : _d( new Private() )
71 {
72 }
73 
TextAttributes(const TextAttributes & r)74 TextAttributes::TextAttributes( const TextAttributes& r )
75     : _d( new Private( *r.d ) )
76 {
77 
78 }
79 
operator =(const TextAttributes & r)80 TextAttributes & TextAttributes::operator=( const TextAttributes& r )
81 {
82     if ( this == &r )
83         return *this;
84 
85     *d = *r.d;
86 
87     return *this;
88 }
89 
~TextAttributes()90 TextAttributes::~TextAttributes()
91 {
92     delete _d; _d = nullptr;
93 }
94 
95 
operator ==(const TextAttributes & r) const96 bool TextAttributes::operator==( const TextAttributes& r ) const
97 {
98     // the following works around a bug in gcc 4.3.2
99     // causing StyleHint to be set to Zero when copying a QFont
100     const QFont myFont( font() );
101     QFont r_font( r.font() );
102     r_font.setStyleHint( myFont.styleHint(), myFont.styleStrategy() );
103     return ( isVisible() == r.isVisible() &&
104              myFont == r_font &&
105              fontSize() == r.fontSize() &&
106              minimalFontSize() == r.minimalFontSize() &&
107              autoRotate() == r.autoRotate() &&
108              autoShrink() == r.autoShrink() &&
109              rotation() == r.rotation() &&
110              pen() == r.pen() &&
111              textDocument() == r.textDocument() );
112 }
113 
114 
setVisible(bool visible)115 void TextAttributes::setVisible( bool visible )
116 {
117     d->visible = visible;
118 }
119 
isVisible() const120 bool TextAttributes::isVisible() const
121 {
122     return d->visible;
123 }
124 
setFont(const QFont & font)125 void TextAttributes::setFont( const QFont& font )
126 {
127     d->font       = font;
128     d->cachedFont = font; // note: we do not set the font's size here, but in calculatedFont()
129     d->cachedFontSize = -1.0;
130 }
131 
font() const132 QFont TextAttributes::font() const
133 {
134     return d->font;
135 }
136 
setFontSize(const Measure & measure)137 void TextAttributes::setFontSize( const Measure & measure )
138 {
139     d->fontSize = measure;
140 }
141 
fontSize() const142 Measure TextAttributes::fontSize() const
143 {
144     return d->fontSize;
145 }
146 
setMinimalFontSize(const Measure & measure)147 void TextAttributes::setMinimalFontSize( const Measure & measure )
148 {
149     d->minimalFontSize = measure;
150 }
151 
minimalFontSize() const152 Measure TextAttributes::minimalFontSize() const
153 {
154     return d->minimalFontSize;
155 }
156 
hasAbsoluteFontSize() const157 bool TextAttributes::hasAbsoluteFontSize() const
158 {
159     return d->fontSize.calculationMode() == KChartEnums::MeasureCalculationModeAbsolute
160         && d->minimalFontSize.calculationMode() == KChartEnums::MeasureCalculationModeAbsolute;
161 }
162 
calculatedFontSize(const QSizeF & referenceSize,KChartEnums::MeasureOrientation autoReferenceOrientation) const163 qreal TextAttributes::calculatedFontSize( const QSizeF &referenceSize,
164                                           KChartEnums::MeasureOrientation autoReferenceOrientation ) const
165 {
166     const qreal normalSize  = fontSize().calculatedValue( referenceSize, autoReferenceOrientation );
167     const qreal minimalSize = minimalFontSize().calculatedValue( referenceSize, autoReferenceOrientation );
168     return qMax( normalSize, minimalSize );
169 }
170 
171 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
172 const
173 #endif
calculatedFontSize(const QObject * autoReferenceArea,KChartEnums::MeasureOrientation autoReferenceOrientation) const174 qreal TextAttributes::calculatedFontSize( const QObject* autoReferenceArea,
175                                           KChartEnums::MeasureOrientation autoReferenceOrientation ) const
176 {
177     const qreal normalSize  = fontSize().calculatedValue( autoReferenceArea, autoReferenceOrientation );
178     const qreal minimalSize = minimalFontSize().calculatedValue( autoReferenceArea, autoReferenceOrientation );
179     return qMax( normalSize, minimalSize );
180 }
181 
calculatedFont(const QObject * autoReferenceArea,KChartEnums::MeasureOrientation autoReferenceOrientation) const182 const QFont TextAttributes::calculatedFont( const QObject* autoReferenceArea,
183                                             KChartEnums::MeasureOrientation autoReferenceOrientation ) const
184 {
185     qreal size = NaN;
186 
187     const CartesianCoordinatePlane* plane = qobject_cast< const CartesianCoordinatePlane* >( autoReferenceArea );
188     if ( plane  && plane->hasFixedDataCoordinateSpaceRelation() ) {
189         // HACK
190         // if hasFixedDataCoordinateSpaceRelation, we use a zoom trick to keep the diagram at a constant size
191         // even when the plane size changes. calculatedFontSize() usually uses the plane size, not the diagram
192         // size, to determine the font size. here we need to give it the diagram size in order to make the font
193         // size constant, too. see KDCHDEV-219.
194         CartesianCoordinatePlane::Private *priv
195             = CartesianCoordinatePlane::Private::get( const_cast< CartesianCoordinatePlane * >( plane ) );
196         size = calculatedFontSize( priv->fixedDataCoordinateSpaceRelationPinnedSize,
197                                    autoReferenceOrientation );
198     } else {
199         size = calculatedFontSize( autoReferenceArea, autoReferenceOrientation );
200     }
201 
202     if ( size > 0.0 && d->cachedFontSize != size ) {
203         d->cachedFontSize = size;
204         d->cachedFont.setPointSizeF( d->cachedFontSize );
205     }
206 
207     return d->cachedFont;
208 }
209 
210 
setAutoRotate(bool autoRotate)211 void TextAttributes::setAutoRotate( bool autoRotate )
212 {
213     d->autoRotate = autoRotate;
214 }
215 
autoRotate() const216 bool TextAttributes::autoRotate() const
217 {
218     return d->autoRotate;
219 }
220 
setAutoShrink(bool autoShrink)221 void TextAttributes::setAutoShrink( bool autoShrink )
222 {
223     d->autoShrink = autoShrink;
224 }
225 
autoShrink() const226 bool TextAttributes::autoShrink() const
227 {
228     return d->autoShrink;
229 }
230 
setRotation(int rotation)231 void TextAttributes::setRotation( int rotation )
232 {
233     d->hasRotation = true;
234     d->rotation = rotation;
235 }
236 
rotation() const237 int TextAttributes::rotation() const
238 {
239     return d->rotation;
240 }
241 
resetRotation()242 void TextAttributes::resetRotation()
243 {
244     d->hasRotation = false;
245     d->rotation = 0;
246 }
247 
hasRotation() const248 bool TextAttributes::hasRotation() const
249 {
250     return d->hasRotation;
251 }
252 
setPen(const QPen & pen)253 void TextAttributes::setPen( const QPen& pen )
254 {
255     d->pen = pen;
256 }
257 
pen() const258 QPen TextAttributes::pen() const
259 {
260     return d->pen;
261 }
262 
textDocument() const263 QTextDocument* TextAttributes::textDocument() const
264 {
265     return d->document.data();
266 }
267 
setTextDocument(QTextDocument * document)268 void TextAttributes::setTextDocument(QTextDocument* document)
269 {
270     d->document = QSharedPointer<QTextDocument>(document);
271 }
272 
273 #if !defined(QT_NO_DEBUG_STREAM)
operator <<(QDebug dbg,const KChart::TextAttributes & ta)274 QDebug operator<<(QDebug dbg, const KChart::TextAttributes& ta)
275 {
276     dbg << "KChart::TextAttributes("
277     << "visible=" << ta.isVisible()
278     << "font=" << ta.font().toString() /* What? No QDebug for QFont? */
279     << "fontsize=" << ta.fontSize()
280     << "minimalfontsize=" << ta.minimalFontSize()
281     << "autorotate=" << ta.autoRotate()
282     << "autoshrink=" << ta.autoShrink()
283     << "rotation=" << ta.rotation()
284     << "pen=" << ta.pen()
285     << ")";
286     return dbg;
287 }
288 #endif /* QT_NO_DEBUG_STREAM */
289