COPASI API  4.16.103
Public Member Functions | Static Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
CQFontRenderer Class Reference

#include <CQFontRenderer.h>

Inheritance diagram for CQFontRenderer:
Inheritance graph
[legend]
Collaboration diagram for CQFontRenderer:
Collaboration graph
[legend]

Public Member Functions

 CQFontRenderer ()
 
virtual std::pair< double, double > getTextureSize (const CLFontSpec &spec, const std::string &text)
 
virtual std::pair
< CLTextTextureSpec *, GLubyte * > 
operator() (const std::string &family, double fontSize, const std::string &text, CLText::FONT_WEIGHT weight=CLText::WEIGHT_NORMAL, CLText::FONT_STYLE style=CLText::STYLE_NORMAL, double zoomFactor=1.0)
 
virtual ~CQFontRenderer ()
 
- Public Member Functions inherited from CLFontRendererBase
virtual ~CLFontRendererBase ()
 

Static Public Member Functions

static std::pair
< CLTextTextureSpec *, GLubyte * > 
createTexture (const std::string &family, double fontSize, const std::string &text, CLText::FONT_WEIGHT weight=CLText::WEIGHT_NORMAL, CLText::FONT_STYLE style=CLText::STYLE_NORMAL, double zoomFactor=1.0)
 

Protected Member Functions

void findSimilarFamily (const std::string &name, std::set< std::string > &families) const
 
void getFamilyList (const std::string &family, std::list< std::string > &list) const
 
QFont getFont (const CLFontSpec &spec)
 
std::pair< CLTextTextureSpec
*, GLubyte * > 
getTexture (QFont &font, const std::string &text, double zoomFactor)
 
std::pair< double, double > getTextureSize (const QFont &font, const std::string &text)
 
void orderFamilies (const std::string &name, const std::set< std::string > &familySet, std::list< std::string > &familyList) const
 

Protected Attributes

std::map< CLFontSpec, QFont > mFontMap
 
QFontDatabase * mpFontDatabase
 

Static Protected Attributes

static CQFontRenderer FONT_RENDERER
 

Detailed Description

Definition at line 23 of file CQFontRenderer.h.

Constructor & Destructor Documentation

CQFontRenderer::CQFontRenderer ( )

Constructor.

Definition at line 45 of file CQFontRenderer.cpp.

46 {
47 }
QFontDatabase * mpFontDatabase
CQFontRenderer::~CQFontRenderer ( )
virtual

Destructor

Definition at line 52 of file CQFontRenderer.cpp.

References mpFontDatabase.

53 {
54  if (this->mpFontDatabase != NULL)
55  {
56  delete this->mpFontDatabase;
57  }
58 }
QFontDatabase * mpFontDatabase

Member Function Documentation

std::pair< CLTextTextureSpec *, GLubyte * > CQFontRenderer::createTexture ( const std::string &  family,
double  fontSize,
const std::string &  text,
CLText::FONT_WEIGHT  weight = CLText::WEIGHT_NORMAL,
CLText::FONT_STYLE  style = CLText::STYLE_NORMAL,
double  zoomFactor = 1.0 
)
static

static method that creates a texture with a static FontRenderer object. This method can be used as a callback.

Definition at line 456 of file CQFontRenderer.cpp.

References FONT_RENDERER.

457 {
458  return FONT_RENDERER(family, fontSize, text, weight, style, zoomFactor);
459 }
static CQFontRenderer FONT_RENDERER
void CQFontRenderer::findSimilarFamily ( const std::string &  name,
std::set< std::string > &  families 
) const
protected

Finds the font families that fit the given family name. A family fits if the name is exactly the same or if the name is contained in the family name. For generic names like sans, serif or monospaced the algorithm tries to find a suitable font family.

Definition at line 401 of file CQFontRenderer.cpp.

References mpFontDatabase.

Referenced by getFamilyList().

402 {
403  QString qname(name.c_str());
404  QStringList familyList = this->mpFontDatabase->families();
405  QStringList::const_iterator constIterator;
406 
407  for (constIterator = familyList.constBegin(); constIterator != familyList.constEnd(); ++constIterator)
408  {
409  if ((*constIterator).contains(name.c_str(), Qt::CaseInsensitive))
410  {
411  families.insert((*constIterator).toLatin1().data());
412  }
413  }
414 }
QFontDatabase * mpFontDatabase
void CQFontRenderer::getFamilyList ( const std::string &  family,
std::list< std::string > &  list 
) const
protected

Definition at line 441 of file CQFontRenderer.cpp.

References findSimilarFamily(), and orderFamilies().

Referenced by getFont().

442 {
443  QString name(family.c_str());
444  name = name.toLower();
445  name = name.trimmed();
446  // find a new font
447  std::set<std::string> familySet;
448  this->findSimilarFamily(family, familySet);
449 
450  if (!familySet.empty())
451  {
452  this->orderFamilies(family, familySet, list);
453  }
454 }
void findSimilarFamily(const std::string &name, std::set< std::string > &families) const
void orderFamilies(const std::string &name, const std::set< std::string > &familySet, std::list< std::string > &familyList) const
QFont CQFontRenderer::getFont ( const CLFontSpec spec)
protected

Returns the font that matches the given FontSpc.

Returns the font that matches the given FontSpec.

Definition at line 80 of file CQFontRenderer.cpp.

References getFamilyList(), CLFontSpec::mFamily, mFontMap, mpFontDatabase, CLFontSpec::mSize, CLFontSpec::mStyle, CLFontSpec::mWeight, CLText::STYLE_ITALIC, CLText::STYLE_NORMAL, and CLText::WEIGHT_BOLD.

Referenced by getTextureSize(), and operator()().

81 {
82  // we only initialize the font database when it is needed for the first time,
83  // hopefully this will resolve the crash under linux if it is instanciated to early.
84  if (this->mpFontDatabase == NULL)
85  {
86  this->mpFontDatabase = new QFontDatabase();
87  }
88 
89  // check if it is a generic font name (sand, serif or monospaced)
90  // and try to find a fitting font
91  // sans: helvetica or arial
92  // serif: times, times new roman or garamond
93  // monospaced: courier, courier new or monaco
94  //std::cout << "Searching font for family \"" << spec.mFamily << "\" with size " << spec.mSize << " weight " << (spec.mWeight==CLText::WEIGHT_BOLD?(const char*)"bold":(const char*)"normal") << " and style " << (spec.mStyle==CLText::STYLE_ITALIC?(const char*)"italic":(const char*)"normal") << "." << std::endl;
95  std::map<CLFontSpec, QFont>::iterator pos;
96  pos = this->mFontMap.find(spec);
97  QFont font;
98  QString styleString;
99 
100  if (spec.mWeight == CLText::WEIGHT_BOLD)
101  {
102  styleString = "Bold";
103  }
104 
105  if (spec.mStyle == CLText::STYLE_ITALIC)
106  {
107  styleString += " Italic";
108  }
109 
110  styleString = styleString.trimmed();
111 
112  if (pos == this->mFontMap.end())
113  {
114  QString family(spec.mFamily.c_str());
115  family = family.toLower();
116 
117  if (family == "sans")
118  {
119  // try helvetica and arial in this order
120  QFont defaultFont;
121  QString defaultFamily = defaultFont.defaultFamily();
122  defaultFont = this->mpFontDatabase->font(defaultFamily, styleString, spec.mSize);
123  CLFontSpec tempSpec = spec;
124  tempSpec.mFamily = "helvetica";
125 
126  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
127  {
128  font = defaultFont;
129  }
130  else
131  {
132  font = this->getFont(tempSpec);
133 
134  if (font == defaultFont)
135  {
136  // if the font is the default font, we try the next one
137  tempSpec.mFamily = "arial";
138 
139  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
140  {
141  font = defaultFont;
142  }
143  else
144  {
145  font = this->getFont(tempSpec);
146  }
147  }
148  }
149  }
150  else if (family == "serif")
151  {
152  // try times, times new roman and garamond in this order
153  QFont defaultFont;
154  QString defaultFamily = defaultFont.defaultFamily();
155  defaultFont = this->mpFontDatabase->font(defaultFamily, styleString, spec.mSize);
156  CLFontSpec tempSpec = spec;
157  tempSpec.mFamily = "times";
158 
159  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
160  {
161  font = defaultFont;
162  }
163  else
164  {
165  font = this->getFont(tempSpec);
166 
167  if (font == defaultFont)
168  {
169  // if the font is the default font, we try the next one
170  tempSpec.mFamily = "times new roman";
171 
172  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
173  {
174  font = defaultFont;
175  }
176  else
177  {
178  font = this->getFont(tempSpec);
179 
180  if (font == defaultFont)
181  {
182  // if the font is the default font, we try the next one
183  tempSpec.mFamily = "garamond";
184 
185  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
186  {
187  font = defaultFont;
188  }
189  else
190  {
191  font = this->getFont(tempSpec);
192  }
193  }
194  }
195  }
196  }
197  }
198  else if (family == "monospaced")
199  {
200  // try courier, courier new and monaco in this order
201  QFont defaultFont;
202  QString defaultFamily = defaultFont.defaultFamily();
203  defaultFont = this->mpFontDatabase->font(defaultFamily, styleString, spec.mSize);
204  CLFontSpec tempSpec = spec;
205  tempSpec.mFamily = "courier";
206 
207  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
208  {
209  font = defaultFont;
210  }
211  else
212  {
213  font = this->getFont(tempSpec);
214 
215  if (font == defaultFont)
216  {
217  // if the font is the default font, we try the next one
218  tempSpec.mFamily = "courier new";
219 
220  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
221  {
222  font = defaultFont;
223  }
224  else
225  {
226  font = getFont(tempSpec);
227 
228  if (font == defaultFont)
229  {
230  // if the font is the default font, we try the next one
231  tempSpec.mFamily = "monaco";
232 
233  if (defaultFamily.contains(tempSpec.mFamily.c_str()))
234  {
235  font = defaultFont;
236  }
237  else
238  {
239  font = this->getFont(tempSpec);
240  }
241  }
242  }
243  }
244  }
245  }
246  else
247  {
248  std::list<std::string> familyList;
249  this->getFamilyList(spec.mFamily, familyList);
250  // now create the font for one of the families in the list
251  QFont defaultFont;
252  QString defaultFamily = defaultFont.defaultFamily();
253  defaultFont = this->mpFontDatabase->font(defaultFamily, styleString, spec.mSize);
254 
255  if (!familyList.empty())
256  {
257  // go through the list and check if there is a font in the that
258  // does not return the default font for the given size and
259  // style
260  std::list<std::string>::const_iterator familyIt = familyList.begin(), familyEndit = familyList.end();
261 
262  while (familyIt != familyEndit)
263  {
264  font = QFont(familyIt->c_str(), spec.mSize, (spec.mWeight == CLText::WEIGHT_BOLD) ? QFont::Bold : QFont::Normal, (spec.mStyle == CLText::STYLE_NORMAL) ? false : true);
265 
266  if (font != defaultFont)
267  {
268  break;
269  }
270 
271  ++familyIt;
272  }
273  }
274  else
275  {
276  // return the default font
277  font = defaultFont;
278  }
279  }
280 
281  this->mFontMap.insert(std::pair<CLFontSpec, QFont>(spec, font));
282  }
283  else
284  {
285  font = pos->second;
286  }
287 
288  //std::cout << "Using font family \"" << font.mFamily().toLatin1().data() << "\" with size " << font.pointSize() << " weight " << (font.bold()?(const char*)"bold":(const char*)"normal") << " and style " << (font.italic()?(const char*)"italic":(const char*)"normal") << "." << std::endl;
289  return font;
290 }
QFont getFont(const CLFontSpec &spec)
void getFamilyList(const std::string &family, std::list< std::string > &list) const
CLText::FONT_WEIGHT mWeight
std::map< CLFontSpec, QFont > mFontMap
QFontDatabase * mpFontDatabase
std::string mFamily
CLText::FONT_STYLE mStyle
std::pair< CLTextTextureSpec *, GLubyte * > CQFontRenderer::getTexture ( QFont &  font,
const std::string &  text,
double  zoomFactor 
)
protected

Creates a texture for the given text using the given font object. The caller has to free the memory for the TextureSpec object and the pData in the TextureSpec object.

zoomFactor

zoomFactor

Definition at line 317 of file CQFontRenderer.cpp.

References getTextureSize(), CLTextTextureSpec::mAscent, CLTextTextureSpec::mMaxScale, CLTextureSpec::mNumComponents, CLTextTextureSpec::mScale, CLTextureSpec::mTextHeight, CLTextureSpec::mTextureHeight, CLTextureSpec::mTextureName, CLTextureSpec::mTextureWidth, and CLTextureSpec::mTextWidth.

Referenced by operator()().

318 {
319  CLTextTextureSpec* pSpec = NULL;
320  // find out what size the text will have
321  font.setStyleStrategy(QFont::ForceOutline);
322  QFontMetrics fontMetrics(font);
323  std::pair<double, double> size = this->getTextureSize(font, text);
324  //std::cout << "texture size: " << size.first << "," << size.second << std::endl;
325  // make the size a power of 2
326  unsigned int exponentWidth = (unsigned int)ceil(log(size.first /** zoomFactor*/ + 2) / log(2.0));
327  unsigned int exponentHeight = (unsigned int)ceil(log(size.second /** zoomFactor*/ + 2) / log(2.0));
328  unsigned int width = 1 << exponentWidth;
329  unsigned int height = 1 << exponentHeight;
330  // draw the text somewhere with white stroke on black background
331  QImage image(width, height, QImage::Format_RGB32);
332  QPainter painter(&image);
333  painter.setBackground(Qt::black);
334  painter.setPen(QPen(QColor(255, 255, 255, 255), 0.25, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin));
335  painter.setBrush(Qt::NoBrush);
336  painter.setFont(font);
337  painter.eraseRect(0, 0, width, height);
338  // move over by 1,1 to get a small edge around the text
339  painter.translate(1.0, 1.0);
340  // we scale after the erase so that we don't have to divide the width and
341  // the height
342  //painter.scale(zoomFactor, zoomFactor);
343  painter.drawText(0.0, fontMetrics.ascent() + 1, text.c_str());
344  painter.end();
345  // convert the image to an OpenGL texture
346  image = QGLWidget::convertToGLFormat(image);
347  // create the texture spec
348  pSpec = new CLTextTextureSpec();
349  pSpec->mTextureWidth = width;
350  pSpec->mTextureHeight = height;
351  pSpec->mTextWidth = size.first;
352  pSpec->mTextHeight = size.second;
353  pSpec->mScale = zoomFactor;
354  pSpec->mMaxScale = -1.0;
355  pSpec->mNumComponents = 1;
356  pSpec->mTextureName = 0;
357  GLint w = 0;
358  GLenum format = GL_ALPHA;
359  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
360  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
361 
362  while (w == 0 && width > 1 && height > 1)
363  {
364  // divide the size by two in each direction
365  width = width >> 1;
366  height = height >> 1;
367  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
368  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
369  }
370 
371  GLubyte* textureData = NULL;
372 
373  if (w != 0)
374  {
375  if (w != pSpec->mTextureWidth)
376  {
377  pSpec->mTextureWidth = width;
378  pSpec->mTextureHeight = height;
379  }
380 
381  textureData = new GLubyte[width * height];
382  pSpec->mAscent = (double)fontMetrics.ascent();
383  unsigned int i, iMax = width * height;
384 
385  for (i = 0; i < iMax; ++i)
386  {
387  textureData[i] = image.bits()[4 * i];
388  }
389  }
390 
391  return std::pair<CLTextTextureSpec*, GLubyte*>(pSpec, textureData);
392 }
double mTextureWidth
double mTextureHeight
virtual std::pair< double, double > getTextureSize(const CLFontSpec &spec, const std::string &text)
unsigned int mNumComponents
std::pair< double, double > CQFontRenderer::getTextureSize ( const CLFontSpec spec,
const std::string &  text 
)
virtual

Returns the size for a font given a font, a text and a zoom factor.

Implements CLFontRendererBase.

Definition at line 306 of file CQFontRenderer.cpp.

References getFont().

Referenced by getTexture().

307 {
308  QFont font = this->getFont(spec);
309  return this->getTextureSize(font, text);
310 }
QFont getFont(const CLFontSpec &spec)
virtual std::pair< double, double > getTextureSize(const CLFontSpec &spec, const std::string &text)
std::pair< double, double > CQFontRenderer::getTextureSize ( const QFont &  font,
const std::string &  text 
)
protected

Returns the size for a font given a font specification, a text and a zoom factor.

Definition at line 295 of file CQFontRenderer.cpp.

296 {
297  QFontMetrics fontMetrics(font);
298  int textWidthInPixels = fontMetrics.width(text.c_str()) + 2;
299  int textHeightInPixels = fontMetrics.height() + 2;
300  return std::pair<double, double>(textWidthInPixels, textHeightInPixels);
301 }
std::pair< CLTextTextureSpec *, GLubyte * > CQFontRenderer::operator() ( const std::string &  family,
double  fontSize,
const std::string &  text,
CLText::FONT_WEIGHT  weight = CLText::WEIGHT_NORMAL,
CLText::FONT_STYLE  style = CLText::STYLE_NORMAL,
double  zoomFactor = 1.0 
)
virtual

Functor that returns a TextureSpec objct with a texture for the given font family, font size font weight, font style and text. The caller is responsible to free the memory of the TextureSpec object and of the pData in the TextureSpec.

Functor that returns a TextureSpec object with a texture for the given font family, font size font weight, font style and text. The caller is responsible to free the memory of the TextureSpec object and of the pData in the TextureSpec.

Implements CLFontRendererBase.

Definition at line 66 of file CQFontRenderer.cpp.

References getFont(), getTexture(), CLFontSpec::mFamily, CLFontSpec::mSize, CLFontSpec::mStyle, and CLFontSpec::mWeight.

67 {
68  CLFontSpec spec;
69  spec.mFamily = family;
70  spec.mSize = fontSize * zoomFactor;
71  spec.mWeight = weight;
72  spec.mStyle = style;
73  QFont font = this->getFont(spec);
74  return getTexture(font, text, zoomFactor);
75 }
QFont getFont(const CLFontSpec &spec)
std::pair< CLTextTextureSpec *, GLubyte * > getTexture(QFont &font, const std::string &text, double zoomFactor)
CLText::FONT_WEIGHT mWeight
std::string mFamily
CLText::FONT_STYLE mStyle
void CQFontRenderer::orderFamilies ( const std::string &  name,
const std::set< std::string > &  familySet,
std::list< std::string > &  familyList 
) const
protected

Given a certain name and a set of font family names, the algorithm tries to put them in an order from best match to worst match.

Definition at line 420 of file CQFontRenderer.cpp.

Referenced by getFamilyList().

421 {
422  std::set<std::string>::const_iterator it = familySet.begin();
423  std::set<std::string>::const_iterator endit = familySet.end();
424 
425  // simple version only copies the set
426  while (it != endit)
427  {
428  // TODO If the name is equal to the current iterator, we insert it before
429  // TODO the first item that is not equal
430  // TODO If the current item starts with the name, we add it before the
431  // TODO first one that starts with the name and has a longer string.
432  // TODO If the name is somewhere in the items string, we add it before
433  // TODO the first entry that does contain the name, but is longer.
434  // TODO For this comparison, we should take thefoundary into account
435  // TODO and maybe remove it befoe comparing
436  familyList.push_back(*it);
437  ++it;
438  }
439 }

Member Data Documentation

CQFontRenderer CQFontRenderer::FONT_RENDERER
staticprotected

Static instance of CQFontRenderer for use in a static function that can be used as a callback.

Definition at line 102 of file CQFontRenderer.h.

Referenced by createTexture().

std::map<CLFontSpec, QFont> CQFontRenderer::mFontMap
protected

A map that stores the font that matches a given spec the best.

Definition at line 100 of file CQFontRenderer.h.

Referenced by getFont().

QFontDatabase* CQFontRenderer::mpFontDatabase
protected

An instance of the font database. It has to be a pointer since there seems to be a problem under linux if an instance of QFontDatabase is created before some other things have been instanciated. At least the application crashed when I made this an object instead of a pointer.

Definition at line 95 of file CQFontRenderer.h.

Referenced by findSimilarFamily(), getFont(), and ~CQFontRenderer().


The documentation for this class was generated from the following files: