Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
CoreText.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlGraphics/CoreText.hpp>
34 #include <vlGraphics/Actor.hpp>
35 #include <vlCore/Log.hpp>
36 
37 #include <ft2build.h>
38 #include FT_FREETYPE_H
39 
40 using namespace vl;
41 
42 // mic fixme: implement me.
43 
44 // Goals:
45 // - Run on OpenGL Core/ES.
46 // - Achieve a much greater rendering speed.
47 // - In order to do this we might sacrifice some of the usability of vl::Text
48 
49 // Guidelines:
50 // - Viewport alignment, text transformation, transform tracking done externally.
51 // - Does not manipulate the GL_PROJECTION and GL_MODELVIEW matrices.
52 // - Text geometry and bounding boxes should be pre-computed on text change.
53 // - Line splitting should not be done at rendering time.
54 // - Should use only OpenGL Core routines.
55 // - Should use texture atlases and perform lazy texture binding.
56 // - Cleaner left to right / right to left text reversing.
57 // - Outline rendering should use 2 pass with enlarged glyphs instead of 5 passes or precompute an high quality outline texture.
58 // - Avoid using doubles and floats if possible, use integer and Rect rather floats and AABBs.
59 
60 //-----------------------------------------------------------------------------
61 void CoreText::render_Implementation(const Actor* actor, const Shader*, const Camera* camera, OpenGLContext* gl_context) const
62 {
63  gl_context->bindVAS(NULL, false, false);
64 
65  VL_CHECK(font())
66 
67  if (!font() || !font()->mFT_Face)
68  return;
69 
70  if ( text().empty() )
71  return;
72 
73  // Lighting can be enabled or disabled.
74  // glDisable(GL_LIGHTING);
75 
76  // Blending must be enabled explicity by the vl::Shader, also to perform z-sort.
77  // glEnable(GL_BLEND);
78 
79  // Trucchetto che usiamo per evitare z-fighting:
80  // Pass #1 - fill color and stencil
81  // - disable depth write mask
82  // - depth test can be enabled or not by the user
83  // - depth func can be choosen by the user
84  // - render in the order: background, border, shadow, outline, text
85  // Pass #2 - fill z-buffer
86  // - enable depth write mask
87  // - disable color mask
88  // - disable stencil
89  // - drawing background and border
90 
91  // Pass #1
92 
93  // disable z-writing
94  GLboolean depth_mask=0;
95  glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask);
96  glDepthMask(GL_FALSE);
97 
98  // background
99  if (backgroundEnabled())
100  renderBackground( actor, camera );
101 
102  // border
103  if (borderEnabled())
104  renderBorder( actor, camera );
105 
106  // to have the most correct results we should render the text twice one for color and stencil, the other for the z-buffer
107 
108  // shadow render
109  if (shadowEnabled())
110  renderText( actor, camera, shadowColor(), shadowVector() );
111  // outline render
112  if (outlineEnabled())
113  {
114  renderText( actor, camera, outlineColor(), fvec2(-1,0) );
115  renderText( actor, camera, outlineColor(), fvec2(+1,0) );
116  renderText( actor, camera, outlineColor(), fvec2(0,-1) );
117  renderText( actor, camera, outlineColor(), fvec2(0,+1) );
118  }
119  // text render
120  renderText( actor, camera, color(), fvec2(0,0) );
121 
122  // Pass #2
123  // fills the z-buffer (not the stencil buffer): approximated to the text bbox
124 
125  // restores depth mask
126  glDepthMask(depth_mask);
127 
128  if (depth_mask)
129  {
130  // disables writing to the color buffer
131  GLboolean color_mask[4];
132  glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
133  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
134 
135  // disable writing to the stencil buffer
136  int stencil_front_mask=0;
137  glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_mask);
138  int stencil_back_mask=0;
139  if (Has_GL_Version_2_0)
140  glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_mask);
141  glStencilMask(0);
142 
143  // background
144  renderBackground( actor, camera );
145 
146  // border
147  renderBorder( actor, camera );
148 
149  // restores color writing
150  glColorMask(color_mask[0],color_mask[1],color_mask[2],color_mask[3]);
151 
152  // restore the stencil masks
153  glStencilMask(stencil_front_mask);
154  if (Has_GL_Version_2_0)
155  glStencilMaskSeparate(GL_BACK, stencil_back_mask);
156  }
157 }
158 //-----------------------------------------------------------------------------
159 void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const fvec2& offset) const
160 {
161  if(!mFont)
162  {
163  Log::error("CoreText::renderText() error: no Font assigned to the CoreText object.\n");
164  VL_TRAP()
165  return;
166  }
167 
168  if (!font()->mFT_Face)
169  {
170  Log::error("CoreText::renderText() error: invalid FT_Face: probably you tried to load an unsupported font format.\n");
171  VL_TRAP()
172  return;
173  }
174 
175  // mic fixme: these should be pre-computed when the text is set!!!
176 
177  AABB rbbox = rawboundingRect( text() ); // for text alignment
178  VL_CHECK(rbbox.maxCorner().z() == 0)
179  VL_CHECK(rbbox.minCorner().z() == 0)
180  AABB bbox = rbbox;
181  bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) );
182  VL_CHECK(bbox.maxCorner().z() == 0)
183  VL_CHECK(bbox.minCorner().z() == 0)
184 
185  // basic render states
186 
187  // mic fixme: detect GLSLProgram and use VertexAttribPointer if present.
188 
189  float texc[] = { 0,0,0,0,0,0,0,0 };
190  VL_glActiveTexture( GL_TEXTURE0 );
191  VL_glClientActiveTexture( GL_TEXTURE0 );
192  glEnable(GL_TEXTURE_2D);
193  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
194  glTexCoordPointer(2, GL_FLOAT, 0, texc);
195 
196  // color
197  glColor4fv(color.ptr());
198 
199  // Constant normal
200  glNormal3fv( fvec3(0,0,1).ptr() );
201 
202  fvec3 vect[4];
203  glEnableClientState( GL_VERTEX_ARRAY );
204  glVertexPointer(3, GL_FLOAT, 0, vect[0].ptr());
205 
206  FT_Long use_kerning = FT_HAS_KERNING( font()->mFT_Face );
207  FT_UInt previous = 0;
208 
209  fvec2 pen(0,0);
210 
211  // mic fixme:
212  // - lines split and lines dimensions (linebox) should be precomputed on text set!
213  // - or convert this function to generate a pre-computed rendering-list!
214 
215  // split the text in different lines
216 
217  VL_CHECK(text().length())
218 
219  std::vector< String > lines;
220  lines.push_back( String() );
221  for(int i=0; i<text().length(); ++i)
222  {
223  if (text()[i] == '\n')
224  {
225  // start new line
226  lines.push_back( String() );
227  }
228  else
229  lines.back() += text()[i];
230  }
231 
232  for(unsigned iline=0; iline<lines.size(); iline++)
233  {
234  // strip spaces at the beginning and at the end of the line
236  lines[iline].trim();
237 
238  AABB linebox = rawboundingRect( lines[iline] );
239  int horz_text_align = 0;
240  int just_space = 0;
241  int just_remained_space = 0;
242  int space_count = 0;
243  for(int c=0; c<(int)lines[iline].length(); c++)
244  if ( lines[iline][c] == ' ' )
245  space_count++;
246 
247  if (space_count && textAlignment() == TextAlignJustify)
248  {
249  just_space = int(rbbox.width() - linebox.width()) / space_count;
250  just_remained_space = int(rbbox.width() - linebox.width()) % space_count;
251  }
252 
253  if (layout() == RightToLeftText)
254  {
255  if (textAlignment() == TextAlignRight)
256  horz_text_align = 0;
257  else
258  if (textAlignment() == TextAlignLeft)
259  horz_text_align = - int(rbbox.width() - linebox.width());
260  else
262  horz_text_align = - int((rbbox.width() - linebox.width()) / 2.0f);
263  }
264  if (layout() == LeftToRightText)
265  {
266  if (textAlignment() == TextAlignRight)
267  horz_text_align = int(rbbox.width() - linebox.width());
268  else
269  if (textAlignment() == TextAlignLeft)
270  horz_text_align = 0;
271  else
273  horz_text_align = + int((rbbox.width() - linebox.width()) / 2.0f);
274  }
275 
276  // this is needed so that empty strings generate empty lines
277  // note that puttig '\n\n\n\n' at the beginning of a text generates
278  // a wrong rendering (see it with background box activated).
279  if (iline != 0 && !lines[iline].length())
280  {
281  pen.y() -= mFont->mHeight;
282  pen.x() = 0;
283  }
284  else
285  for(int c=0; c<(int)lines[iline].length(); c++)
286  {
287  if (c == 0 && iline != 0)
288  {
289  pen.y() -= mFont->mHeight;
290  pen.x() = 0;
291  }
292 
293  const Glyph* glyph = mFont->glyph( lines[iline][c] );
294 
295  if (!glyph)
296  continue;
297 
298  if ( kerningEnabled() && use_kerning && previous && glyph->glyphIndex() )
299  {
300  FT_Vector delta; delta.y = 0;
301  if (layout() == LeftToRightText)
302  {
303  FT_Get_Kerning( font()->mFT_Face, previous, glyph->glyphIndex(), FT_KERNING_DEFAULT, &delta );
304  pen.x() += delta.x / 64.0f;
305  }
306  else
307  if (layout() == RightToLeftText)
308  {
309  FT_Get_Kerning( font()->mFT_Face, glyph->glyphIndex(), previous, FT_KERNING_DEFAULT, &delta );
310  pen.x() -= delta.x / 64.0f;
311  }
312  pen.y() += delta.y / 64.0f;
313  }
314  previous = glyph->glyphIndex();
315 
316  if (glyph->textureHandle())
317  {
318  glBindTexture( GL_TEXTURE_2D, glyph->textureHandle() );
319 
320  texc[0] = glyph->s0();
321  texc[1] = glyph->t1();
322  texc[2] = glyph->s1();
323  texc[3] = glyph->t1();
324  texc[4] = glyph->s1();
325  texc[5] = glyph->t0();
326  texc[6] = glyph->s0();
327  texc[7] = glyph->t0();
328 
329  int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left();
330 
331  vect[0].x() = pen.x() + glyph->width()*0 + left -1;
332  vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
333 
334  vect[1].x() = pen.x() + glyph->width()*1 + left +1;
335  vect[1].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
336 
337  vect[2].x() = pen.x() + glyph->width()*1 + left +1;
338  vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
339 
340  vect[3].x() = pen.x() + glyph->width()*0 + left -1;
341  vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
342 
343  if (layout() == RightToLeftText)
344  {
345  vect[0].x() -= glyph->width()-1 +2;
346  vect[1].x() -= glyph->width()-1 +2;
347  vect[2].x() -= glyph->width()-1 +2;
348  vect[3].x() -= glyph->width()-1 +2;
349  }
350 
351  vect[0].y() -= mFont->mHeight;
352  vect[1].y() -= mFont->mHeight;
353  vect[2].y() -= mFont->mHeight;
354  vect[3].y() -= mFont->mHeight;
355 
356  // normalize coordinate orgin to the bottom/left corner
357  vect[0] -= (fvec3)bbox.minCorner();
358  vect[1] -= (fvec3)bbox.minCorner();
359  vect[2] -= (fvec3)bbox.minCorner();
360  vect[3] -= (fvec3)bbox.minCorner();
361 
362  // margin & horz_text_align
363  vect[0].x() += margin() + horz_text_align;
364  vect[0].y() += margin();
365  vect[1].x() += margin() + horz_text_align;
366  vect[1].y() += margin();
367  vect[2].x() += margin() + horz_text_align;
368  vect[2].y() += margin();
369  vect[3].x() += margin() + horz_text_align;
370  vect[3].y() += margin();
371 
372  // apply offset for outline rendering
373  vect[0].x() += offset.x();
374  vect[0].y() += offset.y();
375  vect[1].x() += offset.x();
376  vect[1].y() += offset.y();
377  vect[2].x() += offset.x();
378  vect[2].y() += offset.y();
379  vect[3].x() += offset.x();
380  vect[3].y() += offset.y();
381 
382  // text pivot
383  for(int i=0; i<4; ++i)
384  {
385  if (textOrigin() & AlignHCenter)
386  {
387  VL_CHECK( !(textOrigin() & AlignRight) )
388  VL_CHECK( !(textOrigin() & AlignLeft) )
389  vect[i].x() -= (int)(bbox.width() / 2.0f);
390  }
391 
392  if (textOrigin() & AlignRight)
393  {
395  VL_CHECK( !(textOrigin() & AlignLeft) )
396  vect[i].x() -= (int)bbox.width();
397  }
398 
399  if (textOrigin() & AlignTop)
400  {
403  vect[i].y() -= (int)bbox.height();
404  }
405 
406  if (textOrigin() & AlignVCenter)
407  {
408  VL_CHECK( !(textOrigin() & AlignTop) )
410  vect[i].y() -= int(bbox.height() / 2.0);
411  }
412  }
413 
414  glDrawArrays(GL_QUADS, 0, 4);
415 
416  #if (0)
417  glDisable(GL_TEXTURE_2D);
418  glColor3fv(vec3(1,0,0).ptr());
419  glDrawArrays(GL_LINE_LOOP, 0, 4);
420  glColor4fv(color.ptr());
421  glEnable(GL_TEXTURE_2D);
422  #endif
423  }
424 
425  if (just_space && lines[iline][c] == ' ' && iline != lines.size()-1)
426  {
427  if (layout() == LeftToRightText)
428  {
429  pen.x() += just_space + (just_remained_space?1:0);
430  // pen.y() += glyph->advance().y();
431  }
432  else
433  if (layout() == RightToLeftText)
434  {
435  pen.x() -= just_space + (just_remained_space?1:0);
436  // pen.y() -= glyph->advance().y();
437  }
438  if(just_remained_space)
439  just_remained_space--;
440  }
441 
442  if (layout() == LeftToRightText)
443  {
444  pen.x() += glyph->advance().x();
445  // pen.y() += glyph->advance().y();
446  }
447  else
448  if (layout() == RightToLeftText)
449  {
450  pen.x() -= glyph->advance().x();
451  // pen.y() -= glyph->advance().y();
452  }
453 
454  }
455  }
456 
457  glDisableClientState( GL_VERTEX_ARRAY );
458  glDisableClientState( GL_TEXTURE_COORD_ARRAY );
459 
460  VL_CHECK_OGL();
461 
462  glDisable(GL_TEXTURE_2D);
463  glBindTexture(GL_TEXTURE_2D, 0);
464 }
465 //-----------------------------------------------------------------------------
466 // returns the raw bounding box of the string, i.e. without alignment, margin and matrix transform.
468 {
469  AABB aabb;
470 
471  if(!font())
472  {
473  Log::error("CoreText::rawboundingRect() error: no Font assigned to the CoreText object.\n");
474  VL_TRAP()
475  return aabb;
476  }
477 
478  if (!font()->mFT_Face)
479  {
480  Log::error("CoreText::rawboundingRect() error: invalid FT_Face: probably you tried to load an unsupported font format.\n");
481  VL_TRAP()
482  return aabb;
483  }
484 
485  fvec2 pen(0,0);
486  fvec3 vect[4];
487 
488  FT_Long use_kerning = FT_HAS_KERNING( font()->mFT_Face );
489  FT_UInt previous = 0;
490 
491  for(int c=0; c<(int)text.length(); c++)
492  {
493  if (text[c] == '\n')
494  {
495  pen.y() -= mFont->mHeight ? mFont->mHeight : mFont->mSize;
496  pen.x() = 0;
497  continue;
498  }
499 
500  const ref<Glyph>& glyph = mFont->glyph(text[c]);
501 
502  // if glyph == NULL there was an error during its creation...
503  if (glyph.get() == NULL)
504  continue;
505 
506  if ( kerningEnabled() && use_kerning && previous && glyph->glyphIndex())
507  {
508  FT_Vector delta; delta.y = 0;
509  if (layout() == LeftToRightText)
510  {
511  FT_Get_Kerning( font()->mFT_Face, previous, glyph->glyphIndex(), FT_KERNING_DEFAULT, &delta );
512  pen.x() += delta.x / 64.0f;
513  }
514  else
515  if (layout() == RightToLeftText)
516  {
517  FT_Get_Kerning( font()->mFT_Face, glyph->glyphIndex(), previous, FT_KERNING_DEFAULT, &delta );
518  pen.x() -= delta.x / 64.0f;
519  }
520  pen.y() += delta.y / 64.0f;
521  }
522  previous = glyph->glyphIndex();
523 
524  if ( glyph->textureHandle() )
525  {
526  int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left();
527 
528  vect[0].x() = pen.x() + glyph->width()*0 + left -1;
529  vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
530 
531  vect[1].x() = pen.x() + glyph->width()*1 + left +1;
532  vect[1].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1;
533 
534  vect[2].x() = pen.x() + glyph->width()*1 + left +1;
535  vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
536 
537  vect[3].x() = pen.x() + glyph->width()*0 + left -1;
538  vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;
539 
540  if (layout() == RightToLeftText)
541  {
542  vect[0].x() -= glyph->width()-1 +2;
543  vect[1].x() -= glyph->width()-1 +2;
544  vect[2].x() -= glyph->width()-1 +2;
545  vect[3].x() -= glyph->width()-1 +2;
546  }
547 
548  vect[0].y() -= mFont->mHeight;
549  vect[1].y() -= mFont->mHeight;
550  vect[2].y() -= mFont->mHeight;
551  vect[3].y() -= mFont->mHeight;
552  }
553 
554  aabb.addPoint( (vec3)vect[0] );
555  aabb.addPoint( (vec3)vect[1] );
556  aabb.addPoint( (vec3)vect[2] );
557  aabb.addPoint( (vec3)vect[3] );
558 
559  if (layout() == LeftToRightText)
560  pen += glyph->advance();
561  else
562  if (layout() == RightToLeftText)
563  pen -= glyph->advance();
564  }
565 
566  return aabb;
567 }
568 //-----------------------------------------------------------------------------
569 void CoreText::renderBackground(const Actor*, const Camera*) const
570 {
571  // mic fixme:
572  // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules!
573 
574  // Background color
575  glColor4fv(mBackgroundColor.ptr());
576 
577  // Constant normal
578  glNormal3fv( fvec3(0,0,1).ptr() );
579 
580  vec3 a,b,c,d;
581  AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!!
582  a = bbox.minCorner();
583  b.x() = (float)bbox.maxCorner().x();
584  b.y() = (float)bbox.minCorner().y();
585  c = bbox.maxCorner();
586  d.x() = (float)bbox.minCorner().x();
587  d.y() = (float)bbox.maxCorner().y();
588  // set z to 0
589  a.z() = b.z() = c.z() = d.z() = 0;
590 
591  fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };
592  glEnableClientState( GL_VERTEX_ARRAY );
593  glVertexPointer(3, GL_FLOAT, 0, vect);
594 
595  glDrawArrays(GL_QUADS,0,4);
596 
597  glDisableClientState( GL_VERTEX_ARRAY );
598 }
599 //-----------------------------------------------------------------------------
600 void CoreText::renderBorder(const Actor*, const Camera*) const
601 {
602  // mic fixme:
603  // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules!
604 
605  // Border color
606  glColor4fv(mBorderColor.ptr());
607 
608  // Constant normal
609  glNormal3fv( fvec3(0,0,1).ptr() );
610 
611  vec3 a,b,c,d;
612  AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!!
613  a = bbox.minCorner();
614  b.x() = (float)bbox.maxCorner().x();
615  b.y() = (float)bbox.minCorner().y();
616  c = bbox.maxCorner();
617  d.x() = (float)bbox.minCorner().x();
618  d.y() = (float)bbox.maxCorner().y();
619  // set z to 0
620  a.z() = b.z() = c.z() = d.z() = 0;
621 
622  fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };
623  glEnableClientState( GL_VERTEX_ARRAY );
624  glVertexPointer(3, GL_FLOAT, 0, vect);
625 
626  glDrawArrays(GL_LINE_LOOP,0,4);
627 
628  glDisableClientState( GL_VERTEX_ARRAY );
629 }
630 //-----------------------------------------------------------------------------
632 {
633  return boundingRect(text());
634 }
635 //-----------------------------------------------------------------------------
637 {
638  AABB bbox = rawboundingRect( text );
639  bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) );
640 
641  // normalize coordinate orgin to the bottom/left corner
642  vec3 min = bbox.minCorner() - bbox.minCorner();
643  vec3 max = bbox.maxCorner() - bbox.minCorner();
644 
645  // text pivot
646 
647  if (textOrigin() & AlignHCenter)
648  {
649  VL_CHECK( !(textOrigin() & AlignRight) )
650  VL_CHECK( !(textOrigin() & AlignLeft) )
651  min.x() -= int(bbox.width() / 2.0);
652  max.x() -= int(bbox.width() / 2.0);
653  }
654 
655  if (textOrigin() & AlignRight)
656  {
658  VL_CHECK( !(textOrigin() & AlignLeft) )
659  min.x() -= (int)bbox.width();
660  max.x() -= (int)bbox.width();
661  }
662 
663  if (textOrigin() & AlignTop)
664  {
667  min.y() -= (int)bbox.height();
668  max.y() -= (int)bbox.height();
669  }
670 
671  if (textOrigin() & AlignVCenter)
672  {
673  VL_CHECK( !(textOrigin() & AlignTop) )
675  min.y() -= int(bbox.height() / 2.0);
676  max.y() -= int(bbox.height() / 2.0);
677  }
678 
679  AABB aabb;
680  aabb.setMinCorner(min);
681  aabb.setMaxCorner(max);
682  return aabb;
683 }
684 //-----------------------------------------------------------------------------
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
float s0() const
Definition: Font.hpp:86
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
int left() const
Definition: Font.hpp:80
const T * get() const
Definition: Object.hpp:128
bool borderEnabled() const
If true draws a rectangular border around the text.
Definition: CoreText.hpp:102
ETextLayout layout() const
Text layout: left to right, right to left.
Definition: CoreText.hpp:82
int width() const
Definition: Font.hpp:74
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
const T_Scalar & z() const
Definition: Vector3.hpp:91
void renderBackground(const Actor *actor, const Camera *camera) const
Definition: CoreText.cpp:569
int top() const
Definition: Font.hpp:83
Represents an OpenGL context, possibly a widget or a pbuffer, which can also respond to keyboard...
The Glyph associated to a character of a given Font.
Definition: Font.hpp:55
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void renderBorder(const Actor *actor, const Camera *camera) const
Definition: CoreText.cpp:600
int textOrigin() const
The origin of the text (pivot point for offsetting and rotations).
Definition: CoreText.hpp:92
int margin() const
The margin to be left around the text.
Definition: CoreText.hpp:70
unsigned int textureHandle() const
Definition: Font.hpp:71
void renderText(const Actor *, const Camera *camera, const fvec4 &color, const fvec2 &offset) const
Definition: CoreText.cpp:159
AABB boundingRect() const
Returns the plain 2D bounding box of the text, in local coordinates.
Definition: CoreText.cpp:631
Visualization Library main namespace.
virtual void render_Implementation(const Actor *actor, const Shader *shader, const Camera *camera, OpenGLContext *gl_context) const
Definition: CoreText.cpp:61
int length() const
Returns the length of the string.
Definition: String.hpp:133
Vector2< float > fvec2
A 2 components vector with float precision.
Definition: Vector2.hpp:282
const fvec2 & advance() const
Definition: Font.hpp:98
#define VL_TRAP()
Definition: checks.hpp:70
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
AABB rawboundingRect(const String &text) const
Definition: CoreText.cpp:467
const fvec4 & color() const
The color of the text.
Definition: CoreText.hpp:65
float t0() const
Definition: Font.hpp:89
ETextAlign textAlignment() const
Text alignment: left, right, center, justify.
Definition: CoreText.hpp:87
real width() const
Returns the width of the AABB computed as max.x - min.x.
Definition: AABB.cpp:151
bool kerningEnabled() const
If enabled text rendering uses kerning information for better quality results (slower).
Definition: CoreText.hpp:97
const vec3 & maxCorner() const
Returns the corner of the AABB with the maximum x y z coordinates.
Definition: AABB.hpp:193
float max(float a, float b)
Definition: Vector2.hpp:311
float min(float a, float b)
Definition: Vector2.hpp:307
void setMinCorner(real x, real y, real z)
Sets the corner of the AABB with the minimum x y z coordinates.
Definition: AABB.hpp:196
int height() const
Definition: Font.hpp:77
const fvec4 & outlineColor() const
The color of the character outline.
Definition: CoreText.hpp:127
void setMaxCorner(real x, real y, real z)
Sets the corner of the AABB with the maximum x y z coordinates.
Definition: AABB.hpp:202
void addPoint(const vec3 &p, real radius)
Updates the AABB to contain the given point.
Definition: AABB.cpp:135
const T_Scalar & y() const
Definition: Vector3.hpp:90
bool outlineEnabled() const
If true the characters are drawn with an outline.
Definition: CoreText.hpp:122
unsigned int glyphIndex() const
Definition: Font.hpp:101
#define NULL
Definition: OpenGLDefs.hpp:81
Manages most of the OpenGL rendering states responsible of the final aspect of the rendered objects...
Definition: Shader.hpp:1830
const vec3 & minCorner() const
Returns the corner of the AABB with the minimum x y z coordinates.
Definition: AABB.hpp:190
const fvec4 & shadowColor() const
The color of the text shadow.
Definition: CoreText.hpp:137
void bindVAS(const IVertexAttribSet *vas, bool use_vbo, bool force)
Activates the specified vertex attribute set - For internal use only.
#define VL_CHECK_OGL()
Definition: OpenGL.hpp:156
fvec3 vec3
Defined as: &#39;typedef fvec3 vec3&#39;. See also VL_PIPELINE_PRECISION.
Definition: Vector3.hpp:269
T_Scalar * ptr()
Definition: Vector4.hpp:98
const fvec2 & shadowVector() const
The offset vector of the shadow.
Definition: CoreText.hpp:142
bool Has_GL_Version_2_0
Definition: OpenGL.cpp:54
const T_Scalar & x() const
Definition: Vector3.hpp:89
float t1() const
Definition: Font.hpp:95
bool backgroundEnabled() const
If true draws a rectangular background below the text.
Definition: CoreText.hpp:112
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
const T_Scalar & x() const
Definition: Vector2.hpp:132
T length(T v)
Definition: glsl_math.hpp:1084
Represents a virtual camera defining, among other things, the point of view from which scenes can be ...
Definition: Camera.hpp:50
bool shadowEnabled() const
If true a sort of shadow is rendered below the text.
Definition: CoreText.hpp:132
float s1() const
Definition: Font.hpp:92
const Font * font() const
The font to be used to render the text.
Definition: CoreText.hpp:75
const T_Scalar & y() const
Definition: Vector2.hpp:133
fvec4 mBorderColor
Definition: CoreText.hpp:171
#define VL_CHECK(expr)
Definition: checks.hpp:73
ref< Font > mFont
Definition: CoreText.hpp:168
fvec4 mBackgroundColor
Definition: CoreText.hpp:172
const String & text() const
The text to be rendered.
Definition: CoreText.hpp:60
real height() const
Returns the height of the AABB computed as max.y - min.y.
Definition: AABB.cpp:158