QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsfontutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfontutils.h
3  ---------------------
4  begin : June 5, 2013
5  copyright : (C) 2013 by Larry Shaffer
6  email : larrys at dakotacarto dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsfontutils.h"
17 
18 #include <QApplication>
19 #include <QFont>
20 #include <QFontDatabase>
21 #include <QFontInfo>
22 #include <QStringList>
23 
24 
25 bool QgsFontUtils::fontMatchOnSystem( const QFont& f )
26 {
27  QFontInfo fi = QFontInfo( f );
28  return fi.exactMatch();
29 }
30 
31 bool QgsFontUtils::fontFamilyOnSystem( const QString& family )
32 {
33  QFont tmpFont = QFont( family );
34  // compare just beginning of family string in case 'family [foundry]' differs
35  return family.startsWith( tmpFont.family(), Qt::CaseInsensitive );
36 }
37 
38 bool QgsFontUtils::fontFamilyMatchOnSystem( const QString& family, QString* chosen, bool* match )
39 {
40  QFontDatabase fontDB;
41  QStringList fontFamilies = fontDB.families();
42  bool found = false;
43 
44  QList<QString>::const_iterator it = fontFamilies.constBegin();
45  for ( ; it != fontFamilies.constEnd(); ++it )
46  {
47  // first compare just beginning of 'family [foundry]' string
48  if ( it->startsWith( family, Qt::CaseInsensitive ) )
49  {
50  found = true;
51  // keep looking if match info is requested
52  if ( match )
53  {
54  // full 'family [foundry]' strings have to match
55  *match = ( *it == family );
56  if ( *match )
57  break;
58  }
59  else
60  {
61  break;
62  }
63  }
64  }
65 
66  if ( found )
67  {
68  if ( chosen )
69  {
70  // retrieve the family actually assigned by matching algorithm
71  QFont f = QFont( family );
72  *chosen = f.family();
73  }
74  }
75  else
76  {
77  if ( chosen )
78  {
79  *chosen = QString();
80  }
81 
82  if ( match )
83  {
84  *match = false;
85  }
86  }
87 
88  return found;
89 }
90 
91 bool QgsFontUtils::updateFontViaStyle( QFont& f, const QString& fontstyle, bool fallback )
92 {
93  if ( fontstyle.isEmpty() )
94  {
95  return false;
96  }
97 
98  QFontDatabase fontDB;
99 
100  if ( !fallback )
101  {
102  // does the font even have the requested style?
103  bool hasstyle = false;
104  foreach ( const QString &style, fontDB.styles( f.family() ) )
105  {
106  if ( style == fontstyle )
107  {
108  hasstyle = true;
109  break;
110  }
111  }
112 
113  if ( !hasstyle )
114  {
115  return false;
116  }
117  }
118 
119  // is the font's style already the same as requested?
120  if ( fontstyle == fontDB.styleString( f ) )
121  {
122  return true;
123  }
124 
125  int defaultSize = QApplication::font().pointSize(); // QFontDatabase::font() needs an integer for size
126 
127  QFont styledfont;
128  bool foundmatch = false;
129 
130  styledfont = fontDB.font( f.family(), fontstyle, defaultSize );
131  if ( QApplication::font() != styledfont )
132  {
133  foundmatch = true;
134  }
135 
136  // default to first found style if requested style is unavailable
137  // this helps in the situations where the passed-in font has to have a named style applied
138  if ( fallback && !foundmatch )
139  {
140  QFont testFont = QFont( f );
141  testFont.setPointSize( defaultSize );
142 
143  // prefer a style that mostly matches the passed-in font
144  foreach ( const QString &style, fontDB.styles( f.family() ) )
145  {
146  styledfont = fontDB.font( f.family(), style, defaultSize );
147  styledfont = styledfont.resolve( f );
148  if ( testFont.toString() == styledfont.toString() )
149  {
150  foundmatch = true;
151  break;
152  }
153  }
154 
155  // fallback to first style found that works
156  if ( !foundmatch )
157  {
158  foreach ( const QString &style, fontDB.styles( f.family() ) )
159  {
160  styledfont = fontDB.font( f.family(), style, defaultSize );
161  if ( QApplication::font() != styledfont )
162  {
163  foundmatch = true;
164  break;
165  }
166  }
167  }
168  }
169 
170  // similar to QFont::resolve, but font may already have pixel size set
171  // and we want to make sure that's preserved
172  if ( foundmatch )
173  {
174  if ( f.pointSizeF() != -1 )
175  {
176  styledfont.setPointSizeF( f.pointSizeF() );
177  }
178  else if ( f.pixelSize() != -1 )
179  {
180  styledfont.setPixelSize( f.pixelSize() );
181  }
182  styledfont.setCapitalization( f.capitalization() );
183  styledfont.setUnderline( f.underline() );
184  styledfont.setStrikeOut( f.strikeOut() );
185  styledfont.setWordSpacing( f.wordSpacing() );
186  styledfont.setLetterSpacing( QFont::AbsoluteSpacing, f.letterSpacing() );
187  f = styledfont;
188 
189  return true;
190  }
191 
192  return false;
193 }