Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PaintText Class Reference

#include <painttext.h>

Classes

struct  LayoutState
 
struct  TextFragment
 
struct  TextLine
 

Public Types

enum  WidthExceeded { FULL_WIDTH, ELLIPSIS, MULTI_LINE }
 

Public Member Functions

virtual void setRect (const Rect &r)
 
virtual Rect rect (void) const
 
virtual void setText (const std::string &text)
 
virtual const std::string & text (void) const
 
virtual void setColor (const GFXColor &c)
 
virtual GFXColor color (void) const
 
virtual void setFont (const Font &f)
 
virtual Font font (void) const
 
virtual void setJustification (Justification j)
 
virtual Justification justification (void) const
 
virtual void setWidthExceeded (WidthExceeded w)
 
virtual WidthExceeded widthExceeded (void) const
 
virtual int lineCount (void) const
 
virtual int visibleLineCountStartingWith (int lineNumber, float vertInterval) const
 
virtual int layoutVersion (void) const
 
virtual void drawLines (size_t start, size_t count=END_LINE) const
 
void draw (void) const
 
 PaintText (void)
 
 PaintText (const Rect &rect, const std::string &text, const Font &font, const GFXColor &color, Justification just=RIGHT_JUSTIFY, WidthExceeded w=ELLIPSIS)
 
virtual ~PaintText (void)
 

Static Public Attributes

static const size_t END_LINE = 1000000
 

Protected Member Functions

void calcLayout (void)
 
void calcLayoutIfNeeded (void) const
 
float lineInset (const TextLine &line)
 
void addFragment (TextLine &line, const std::string::size_type endPos, std::string::size_type &startPos, double &width)
 
void parseFormat (std::string::size_type startPos, std::string::size_type *resultPos, bool *endLine)
 
void parseFragmentsWithCharBreak (TextLine &line, std::string::size_type startPos, std::string::size_type endPos, float maxWidth, bool ellipsis, std::string::size_type *resultPos)
 
void parseFragmentsWithWordBreak (TextLine &line, std::string::size_type startPos, float maxWidth, std::string::size_type *resultPos)
 

Protected Attributes

Rect m_rect
 
std::string m_text
 
GFXColor m_color
 
Font m_font
 
Justification m_justification
 
WidthExceeded m_widthExceeded
 
bool m_needLayout
 
int m_layoutVersion
 
vector< TextLinem_lines
 
double m_verticalScaling
 
double m_horizontalScaling
 
LayoutState m_layout
 

Detailed Description

Definition at line 75 of file painttext.h.

Member Enumeration Documentation

Enumerator
FULL_WIDTH 
ELLIPSIS 
MULTI_LINE 

Definition at line 114 of file painttext.h.

115  {
116  FULL_WIDTH, //Do nothing. Just do one line of text.
117  ELLIPSIS, //Put an ellipsis at the end of the text.
118  MULTI_LINE //Go to the next line.
119  };

Constructor & Destructor Documentation

PaintText::PaintText ( void  )

Definition at line 760 of file painttext.cpp.

760  :
761  m_rect()
762  , m_text()
764  , m_font()
767  , m_needLayout( true )
768  , m_layoutVersion( 0 )
769  , m_verticalScaling( 0.7 )
770  , m_horizontalScaling( 0.7 )
771 {
772 }
PaintText::PaintText ( const Rect rect,
const std::string &  text,
const Font font,
const GFXColor color,
Justification  just = RIGHT_JUSTIFY,
WidthExceeded  w = ELLIPSIS 
)

Definition at line 774 of file painttext.cpp.

References setText().

775  :
776  m_rect( r )
777  , m_text()
778  , //Don't set text here.
779  m_color( c )
780  , m_font( f )
781  , m_justification( j )
782  , m_widthExceeded( w )
783  , m_needLayout( true )
784  , m_layoutVersion( 0 )
785  , m_verticalScaling( 0.7 )
786  , m_horizontalScaling( 0.7 )
787 {
788  setText( t ); //Do conversion if necessary.
789 }
virtual PaintText::~PaintText ( void  )
inlinevirtual

Definition at line 153 of file painttext.h.

153 {}

Member Function Documentation

void PaintText::addFragment ( TextLine line,
const std::string::size_type  endPos,
std::string::size_type &  startPos,
double &  width 
)
protected

Definition at line 432 of file painttext.cpp.

References Font::charWidth(), charWidth(), PaintText::TextFragment::color, PaintText::LayoutState::colorStack, PaintText::TextFragment::end, font(), PaintText::TextFragment::font, PaintText::LayoutState::fontStack, PaintText::TextLine::fragments, m_layout, m_text, and PaintText::TextFragment::start.

Referenced by parseFragmentsWithCharBreak().

437 {
438  string::size_type curPos = startPos;
439  const Font &font = m_layout.fontStack.back();
440  //Loop through the characters until we run out of room.
441  while (curPos < endPos) {
442  double charWidth = font.charWidth( m_text[curPos] );
443  if (width-charWidth < 0.0)
444  //The current character goes past the specified width.
445  break;
446  width -= charWidth;
447  curPos++;
448  }
449  //Create the fragment.
450  if (curPos > startPos) {
451  TextFragment frag;
452  frag.start = startPos;
453  frag.end = curPos-1; //Last char in frag, not one past.
454  frag.font = font;
455  frag.color = m_layout.colorStack.back();
456  line.fragments.push_back( frag );
457  }
458  startPos = curPos;
459 }
void PaintText::calcLayout ( void  )
protected

Definition at line 674 of file painttext.cpp.

References PaintText::TextLine::baseLine, BOGUS_LINE_SPACING, PaintText::LayoutState::colorStack, PaintText::LayoutState::currentLineSpacing, ELLIPSIS, PaintText::LayoutState::fontStack, PaintText::TextLine::fragments, VegaConfig::getVariable(), Size::height, PaintText::TextLine::height, Font::horizontalScaling(), lineInset(), LINES_RESERVE, m_color, m_font, m_horizontalScaling, m_layout, m_layoutVersion, m_lines, m_needLayout, m_rect, m_text, m_verticalScaling, m_widthExceeded, MULTI_LINE, XMLSupport::parse_float(), parseFragmentsWithCharBreak(), parseFragmentsWithWordBreak(), PaintText::LayoutState::permanentLineSpacing, REFERENCE_BASELINE_POS, REFERENCE_FONT_ASCENDER, Font::size(), Rect::size, Font::verticalScaling(), vs_config, Size::width, and PaintText::TextLine::x.

Referenced by calcLayoutIfNeeded().

675 {
676  //Clear the old layout.
677  m_lines.clear();
678  //Make sure the version number changes.
679  m_layoutVersion++;
680  //Make sure we don't call this again unless we need to.
681  m_needLayout = false;
682  if ( m_text.empty() )
683  return;
684  //Scaling factors.
687  //Max line width in character reference space.
688  static float font_width_hack = XMLSupport::parse_float( vs_config->getVariable( "graphics", "font_width_hack", "0.925" ) );
689  const float maxLineWidth = m_rect.size.width*font_width_hack/m_horizontalScaling;
690  //The temporary global state for the layout operation.
691  //Make sure this gets initialized at the beginning of an operation.
692  m_layout = LayoutState( 1.0, 1.0 );
693  //Keep track of switches in fonts/colors.
694  m_layout.fontStack.push_back( m_font );
695  m_layout.colorStack.push_back( m_color );
696  //Create the current line.
697  m_lines.reserve( LINES_RESERVE );
698  m_lines.resize( 1 );
699  TextLine *currentLine = &m_lines.back();
700  if (m_widthExceeded != MULTI_LINE) {
701  //SINGLE LINE.
702  currentLine->height = m_rect.size.height;
703  currentLine->baseLine = ( currentLine->height-m_font.size() )/2.0
705 
706  string::size_type ignorePos = 0;
707  bool ellipsis = (m_widthExceeded == ELLIPSIS);
708  parseFragmentsWithCharBreak( *currentLine, 0, m_text.size(), maxLineWidth, ellipsis, &ignorePos );
709 
710  //Need line width before we can set this.
711  currentLine->x = lineInset( *currentLine );
712  //If we got no fragments, get rid of the line.
713  if ( currentLine->fragments.empty() )
714  m_lines.pop_back();
715  } else {
716  //MULTIPLE LINES.
717  int nextLinePos = 0; //The char loc in m_text of the beginning of the next line.
718  while (true) {
719  //Figure vertical measurements before we parse the line.
720  currentLine->height = m_layout.fontStack.back().size()*m_layout.currentLineSpacing;
721  currentLine->baseLine = currentLine->height-m_verticalScaling*REFERENCE_BASELINE_POS;
722 
723  //Get the first line of chars, including the length.
724  string::size_type endNextLinePos = 0;
725  m_layout.currentLineSpacing = BOGUS_LINE_SPACING; //Line spacing for this line only. Bogus value.
726  parseFragmentsWithWordBreak( *currentLine, nextLinePos, maxLineWidth, &endNextLinePos );
728  //We found no format command for current line spacing. Use permanent spacing.
729  //Need to set this *after* we get the line spacing for this line.
731  }
732  //Horizontal starting position.
733  currentLine->x = lineInset( *currentLine );
734  //See if we're done.
735  if ( endNextLinePos >= m_text.size() )
736  //EXIT FROM LOOP
737  break;
738  //Start of next line.
739  nextLinePos = endNextLinePos;
740  m_lines.resize( m_lines.size()+1 ); //Add a new TextLine.
741  currentLine = &m_lines.back();
742  }
743  }
744 }
void PaintText::calcLayoutIfNeeded ( void  ) const
protected

Definition at line 190 of file painttext.cpp.

References calcLayout(), and m_needLayout.

Referenced by drawLines(), layoutVersion(), lineCount(), and visibleLineCountStartingWith().

191 {
192  if (m_needLayout) {
193  //calcLayout is a cache. Doesn't change the "real" state of the object.
194  PaintText *s = const_cast< PaintText* > (this);
195  s->calcLayout();
196  }
197 }
virtual GFXColor PaintText::color ( void  ) const
inlinevirtual

Definition at line 94 of file painttext.h.

References m_color.

Referenced by parseFormat(), and StaticDisplay::textColor().

95  {
96  return m_color;
97  }
void PaintText::draw ( void  ) const
inline

Definition at line 140 of file painttext.h.

References drawLines().

Referenced by Picker::draw(), and NewButton::draw().

141  {
142  drawLines( 0 );
143  }
void PaintText::drawLines ( size_t  start,
size_t  count = END_LINE 
) const
virtual

Definition at line 218 of file painttext.cpp.

References PaintText::TextLine::baseLine, calcLayoutIfNeeded(), drawChars(), ELLIPSIS_FRAGMENT, ELLIPSIS_STRING, PaintText::TextLine::fragments, GFXBlendMode(), GFXColorf(), GFXPopBlendMode(), GFXPushBlendMode(), GFXToggleTexture(), gl_options, guiMin, PaintText::TextLine::height, i, INVSRCALPHA, LINE_HEIGHT_EPSILON, m_horizontalScaling, m_lines, m_rect, m_text, m_verticalScaling, Rect::origin, gl_options_t::smooth_lines, SRCALPHA, Rect::top(), useStroke(), PaintText::TextLine::x, Point::x, and Point::y.

Referenced by StaticDisplay::draw(), and draw().

219 {
220  //Make sure we hav a display list.
222  //Make sure we have something to do.
223  if ( m_lines.empty() )
224  return;
225  //Initialize the graphics state.
226  GFXToggleTexture( false, 0 );
228  glEnable( GL_LINE_SMOOTH );
231  glPushMatrix();
232  //Keep track of line position.
233  float lineTop = m_rect.top();
234  //Figure ending line index.
235  const size_t end = guiMin( start+count, m_lines.size() );
236  //Loop through the display list lines.
237  for (size_t i = start; i < end; i++) {
238  const TextLine &line = m_lines[i];
239  //Make sure we can paint this line in the vertical space we have left.
240  if (lineTop-line.height*LINE_HEIGHT_EPSILON < m_rect.origin.y)
241  //Not enough space to draw this line.
242  break;
243  //Position at the start of the line.
244  glLoadIdentity();
245  glTranslatef( m_rect.origin.x+line.x, lineTop-line.baseLine, 0.0 );
246  if ( line.fragments.size() )
247  GFXColorf( line.fragments[0].color );
248  if ( !useStroke() )
249  glRasterPos2f( 0, 0 );
250  else
251  glScaled( m_horizontalScaling, m_verticalScaling, 1.0 );
252  float rasterpos = 0;
253  //Draw each fragment.
254  for (vector< TextFragment >::const_iterator frag = line.fragments.begin(); frag != line.fragments.end(); frag++) {
255  if (frag->start == ELLIPSIS_FRAGMENT)
256  //We have a special-case for the ellipsis at the end of a line.
257  drawChars( ELLIPSIS_STRING, 0, 2, frag->font, frag->color, rasterpos );
258  else
259  rasterpos = drawChars( m_text, frag->start, frag->end, frag->font, frag->color, rasterpos );
260  }
261  //Top of next line.
262  lineTop -= line.height;
263  }
264  glRasterPos2f( 0, 0 );
265  //Undo graphics state
266  GFXPopBlendMode();
268  glDisable( GL_LINE_SMOOTH );
269  glPopMatrix();
270  GFXToggleTexture( true, 0 );
271 }
virtual Font PaintText::font ( void  ) const
inlinevirtual

Definition at line 101 of file painttext.h.

References m_font.

Referenced by addFragment(), StaticDisplay::font(), parseFragmentsWithCharBreak(), and parseFragmentsWithWordBreak().

102  {
103  return m_font;
104  }
virtual Justification PaintText::justification ( void  ) const
inlinevirtual

Definition at line 108 of file painttext.h.

References m_justification.

Referenced by StaticDisplay::justification().

109  {
110  return m_justification;
111  }
int PaintText::layoutVersion ( void  ) const
virtual

Definition at line 183 of file painttext.cpp.

References calcLayoutIfNeeded(), and m_layoutVersion.

Referenced by StaticDisplay::draw().

184 {
186  return m_layoutVersion;
187 }
int PaintText::lineCount ( void  ) const
virtual

Definition at line 159 of file painttext.cpp.

References calcLayoutIfNeeded(), and m_lines.

Referenced by StaticDisplay::draw().

160 {
162  return m_lines.size();
163 }
float PaintText::lineInset ( const TextLine line)
protected

Definition at line 662 of file painttext.cpp.

References CENTER_JUSTIFY, LEFT_JUSTIFY, m_horizontalScaling, m_justification, m_rect, Rect::size, Size::width, and PaintText::TextLine::width.

Referenced by calcLayout().

663 {
664  float result = 0.0; //Assume we will RIGHT_JUSTIFY.
666  result = (m_rect.size.width-line.width*m_horizontalScaling)/2.0;
667  else if (m_justification == LEFT_JUSTIFY)
668  result = m_rect.size.width-line.width*m_horizontalScaling;
669  return result;
670 }
void PaintText::parseFormat ( std::string::size_type  startPos,
std::string::size_type *  resultPos,
bool endLine 
)
protected

Definition at line 343 of file painttext.cpp.

References BOGUS_LINE_SPACING, BOLD_STROKE, color(), PaintText::LayoutState::colorStack, PaintText::LayoutState::currentLineSpacing, DT_FORMAT_COLOR_CHAR, DT_FORMAT_LINE_SPACING_CHAR, DT_FORMAT_NEWLINE_CHAR, DT_FORMAT_POP_CHAR, DT_FORMAT_RESET_CHAR, DT_FORMAT_STROKE_CHAR, f, PaintText::LayoutState::fontStack, m_layout, m_text, parseFormatColor(), parseFormatFloat(), and PaintText::LayoutState::permanentLineSpacing.

Referenced by parseFragmentsWithCharBreak(), and parseFragmentsWithWordBreak().

347 {
348  const string::size_type endPos = m_text.size();
349  //Default return value.
350  *endLine = false;
351  bool formatSuccess = false;
352  string::size_type curPos = startPos;
353  if (curPos < endPos) {
354  //Make sure we have some chars to process.
355  switch (m_text[curPos])
356  {
358  //End of line.
359  {
360  float value = BOGUS_LINE_SPACING; //Bogus value.
361  parseFormatFloat( m_text, curPos+1, endPos, &formatSuccess, &value, &curPos );
362  if (formatSuccess) {
363  *endLine = true; //End of this line.
364  if (value != BOGUS_LINE_SPACING)
366  }
367  break;
368  }
370  //New permanent line spacing.
371  {
372  float value = BOGUS_LINE_SPACING; //Bogus value.
373  parseFormatFloat( m_text, curPos+1, endPos, &formatSuccess, &value, &curPos );
374  if (formatSuccess && value != BOGUS_LINE_SPACING)
376  break;
377  }
379  //"Bold" -- change stroke width of font.
380  {
381  float strokeWeight = BOLD_STROKE;
382  parseFormatFloat( m_text, curPos+1, endPos, &formatSuccess, &strokeWeight, &curPos );
383  if (formatSuccess) {
384  Font f( m_layout.fontStack.back() ); //Make a new font.
385  f.setStrokeWeight( strokeWeight );
386  m_layout.fontStack.push_back( f );
387  }
388  break;
389  }
391  //Change the text color.
392  {
393  GFXColor color;
394  parseFormatColor( m_text, curPos+1, endPos, &formatSuccess, color, &curPos );
395  if (formatSuccess)
396  m_layout.colorStack.push_back( color );
397  break;
398  }
399  case DT_FORMAT_POP_CHAR:
400  //Pop a color/font.
401  curPos++;
402  if (curPos == endPos) {
403  *endLine = true;
404  } else if (m_text[curPos] == DT_FORMAT_STROKE_CHAR) {
405  if (m_layout.fontStack.size() > 1) m_layout.fontStack.pop_back();
406  else if (m_text[curPos] == DT_FORMAT_COLOR_CHAR)
407  if (m_layout.colorStack.size() > 1) m_layout.colorStack.pop_back();
408  }
409  curPos++;
410  break;
412  //Reset colors/fonts back to original. Pops all off stack except bottom.
413  curPos++;
414  if (curPos == endPos)
415  *endLine = true;
416  else if (m_text[curPos] == DT_FORMAT_STROKE_CHAR)
417  while (m_layout.fontStack.size() > 1)
418  m_layout.fontStack.pop_back();
419  else if (m_text[curPos] == DT_FORMAT_COLOR_CHAR)
420  while (m_layout.colorStack.size() > 1)
421  m_layout.colorStack.pop_back();
422  curPos++;
423  break;
424  }
425  }
426  *resultPos = curPos;
427 }
void PaintText::parseFragmentsWithCharBreak ( TextLine line,
std::string::size_type  startPos,
std::string::size_type  endPos,
float  maxWidth,
bool  ellipsis,
std::string::size_type *  resultPos 
)
protected

Definition at line 468 of file painttext.cpp.

References addFragment(), Font::charWidth(), DT_FORMAT_CHAR, ELLIPSIS_FRAGMENT, ELLIPSIS_STRING, PaintText::TextFragment::end, font(), PaintText::TextFragment::font, PaintText::LayoutState::fontStack, PaintText::TextLine::fragments, i, isWordBreak(), m_layout, m_text, parseFormat(), PaintText::TextFragment::start, Font::stringWidth(), and PaintText::TextLine::width.

Referenced by calcLayout(), and parseFragmentsWithWordBreak().

475 {
476  string::size_type curPos = startPos; //Beginning of current part of the string we are working on.
477  double curWidth = maxWidth; //The width left to work with.
478  bool forceEndLine = false; //True = end-of-line through format. False = char width.
479  while (curPos < endPos) {
480  //Is there a format char left in this string?
481  const string::size_type formatPos = m_text.find( DT_FORMAT_CHAR, curPos );
482  if (formatPos == std::string::npos || formatPos >= endPos) {
483  //No format char.
484  addFragment( line, endPos, curPos, curWidth );
485  break;
486  }
487  //Create fragment for characters before the format char.
488  addFragment( line, formatPos, curPos, curWidth );
489  if (curPos < formatPos)
490  //Format is past the max width. We're done with this line.
491  break;
492  //Interpret the format command.
493  assert( m_text[curPos] == DT_FORMAT_CHAR );
494  curPos++; //Look at the command char.
495  if (curPos >= endPos) {
496  //No command char. String ends with single "#". Ignore it.
497  curPos = endPos-1;
498  break;
499  }
500  if (m_text[curPos] == DT_FORMAT_CHAR) {
501  //Double format char. Equals one format char.
502  const string::size_type oldPos = curPos;
503  addFragment( line, curPos+1, curPos, curWidth );
504  if (curPos == oldPos) {
505  //No room in the line for the one char. Leave it for next line.
506  curPos--; //Put chars back in string.
507  break; //End of this line.
508  }
509  } else {
510  parseFormat( curPos, &curPos, &forceEndLine );
511  if (forceEndLine)
512  break;
513  }
514  }
515  if (!forceEndLine && curPos < endPos) {
516  if (ellipsis) {
517  //We need to append an ellipsis. We didn't use the whole string, and we didn't end
518  //the line because of a format command.
519  //We use the font at the end of the line. This is a hack, but it seems like a
520  //reasonable compromise. If we use the font from the beginning of the line, suppose the
521  //line starts out with bold, followed by a non-bold explanation?
522  //We use the color of the last fragment before the ellipsis.
523 
524  const Font &font = m_layout.fontStack.back();
525  const double ellipsisWidth = font.stringWidth( ELLIPSIS_STRING );
526  //If ellipsis doesn't fit in the original width, just ship the truncated string.
527  if (ellipsisWidth < maxWidth) {
528  while (line.fragments.size() > 0) {
529  TextFragment &frag = line.fragments.back();
530  //Remove enough space in the last fragment to be able to append the ellipsis.
531  string::size_type i;
532  for (i = frag.end; i >= frag.start; i--) {
533  curWidth -= frag.font.charWidth( m_text[i] );
534  if (curWidth+ellipsisWidth <= maxWidth) {
535  //If we back up this far, the ellipsis will fit in the max width.
536  frag.end = i;
537  break;
538  }
539  }
540  if (i < frag.start) {
541  //Used up the whole fragment and still didn't find enough space.
542  line.fragments.pop_back();
543  } else {
544  //Create an ellipsis fragment and append it to the line.
545  TextFragment newFrag = frag;
546  newFrag.start = ELLIPSIS_FRAGMENT;
547  line.fragments.push_back( newFrag );
548  curWidth += ellipsisWidth;
549  break;
550  }
551  }
552  }
553  } else {
554  //Get rid of word break chars at the end of this line.
555  //First, make sure to skip over any white space.
556  while ( curPos < endPos && isWordBreak( m_text[curPos] ) )
557  curPos++;
558  //Now, get rid of any word break chars at the tail end of our fragment list.
559  while (line.fragments.size() > 0) {
560  TextFragment &frag = line.fragments.back();
561  string::size_type i;
562  for (i = frag.end; i >= frag.start; i--) {
563  if ( !isWordBreak( m_text[i] ) )
564  break;
565  curWidth -= frag.font.charWidth( m_text[i] );
566  }
567  if (i >= frag.start)
568  //Found something besides a word break in this fragment.
569  break;
570  //Used up the whole fragment. Start on the next one.
571  line.fragments.pop_back();
572  }
573  }
574  }
575  //Set the width of this line.
576  line.width = maxWidth-curWidth;
577  //And make sure we know how far we got in the string.
578  *resultPos = curPos;
579 }
void PaintText::parseFragmentsWithWordBreak ( TextLine line,
std::string::size_type  startPos,
float  maxWidth,
std::string::size_type *  resultPos 
)
protected

Definition at line 582 of file painttext.cpp.

References Font::charWidth(), charWidth(), DT_FORMAT_CHAR, font(), PaintText::LayoutState::fontStack, isWordBreak(), m_layout, m_text, parseFormat(), and parseFragmentsWithCharBreak().

Referenced by calcLayout().

587 {
588  string::size_type curPos = startPos; //Beginning of current part of the string we are working on.
589  double curWidth = maxWidth; //The width left to work with.
590  const string::size_type endPos = m_text.size(); //One past the end of the string.
591  bool forceEndLine = false; //True = end-of-line through format. False = char width.
592  LayoutState origLayout = m_layout; //The original layout state before we start the line.
593  string::size_type wordBreakPos = endPos; //Previous word break location in text.
594  //In this loop we just measure the width. We find the end of the current line in m_text,
595  //then call parseFragmentsWithCharBreak once we know how far to go.
596  while (curPos < endPos) {
597  //Is there a format char left in this string?
598  const string::size_type formatPos = m_text.find( DT_FORMAT_CHAR, curPos );
599  string::size_type endFragPos = formatPos;
600  if (formatPos == std::string::npos || formatPos >= endPos)
601  //No format char.
602  endFragPos = endPos;
603  //Loop through the characters until we run out of room.
604  const Font &font = m_layout.fontStack.back();
605  while (curPos < endFragPos) {
606  double charWidth = font.charWidth( m_text[curPos] );
607  if ( isWordBreak( m_text[curPos] ) )
608  wordBreakPos = curPos;
609  if (curWidth-charWidth < 0.0)
610  //The current character goes past the specified width.
611  break;
612  curWidth -= charWidth;
613  curPos++;
614  }
615  if (curPos == endPos) {
616  //The rest of the text is not as wide as the max. We are done with this pass.
617  wordBreakPos = endPos;
618  break;
619  } else if (curPos < endFragPos) {
620  //We found a last character. Go back to the last word break.
621  break;
622  }
623  assert( curPos == formatPos ); //Other other case: we ran into a format command.
624  //Interpret the format command.
625  assert( m_text[curPos] == DT_FORMAT_CHAR );
626  curPos++; //Look at the command char.
627  if (curPos >= endPos) {
628  //No command char. String ends with single "#". Ignore it.
629  curPos = endPos-1;
630  break;
631  }
632  if (m_text[curPos] == DT_FORMAT_CHAR) {
633  //Double format char. Equals one format char.
634  curWidth -= font.charWidth( DT_FORMAT_CHAR );
635  if (curWidth < 0.0) {
636  //No room in the line for the one char. Leave it for next line.
637  curPos--; //Put chars back in string.
638  break; //End of this line.
639  }
640  } else {
641  parseFormat( curPos, &curPos, &forceEndLine );
642  if (forceEndLine) {
643  wordBreakPos = endPos;
644  break;
645  }
646  }
647  }
648  //Now we need to generate the fragments.
649  //NOTE: If the text contains a word that is too long for a line, we get a special case
650  //where we never find a word break. That ends up calling parseFragmentsWithCharBreak with
651  //the end of the string as the limit, so the word is broken on a char boundary, which is
652  //exactly what we want.
653  string::size_type endLinePos = wordBreakPos+1;
654  //Include all extra word break characters.
655  while ( endLinePos+1 < endPos && isWordBreak( m_text[endLinePos] ) )
656  endLinePos++;
657  m_layout = origLayout; //Undo any format changes.
658  parseFragmentsWithCharBreak( line, startPos, endLinePos, maxWidth, false, resultPos );
659 }
virtual Rect PaintText::rect ( void  ) const
inlinevirtual

Definition at line 80 of file painttext.h.

References m_rect.

81  {
82  return m_rect;
83  }
void PaintText::setColor ( const GFXColor c)
virtual

Definition at line 123 of file painttext.cpp.

References c, equalColors(), m_color, and m_needLayout.

Referenced by Picker::draw(), NewButton::draw(), and StaticDisplay::setTextColor().

124 {
125  if ( !equalColors( m_color, c ) ) {
126  m_color = c;
127  m_needLayout = true;
128  }
129 }
void PaintText::setFont ( const Font f)
virtual

Definition at line 132 of file painttext.cpp.

References m_font, and m_needLayout.

Referenced by Picker::draw(), NewButton::draw(), and StaticDisplay::setFont().

133 {
134  if (m_font != f) {
135  m_font = f;
136  m_needLayout = true;
137  }
138 }
void PaintText::setJustification ( Justification  j)
virtual

Definition at line 141 of file painttext.cpp.

References m_justification, and m_needLayout.

Referenced by NewButton::draw(), and StaticDisplay::setJustification().

142 {
143  if (m_justification != j) {
144  m_justification = j;
145  m_needLayout = true;
146  }
147 }
void PaintText::setRect ( const Rect r)
virtual

Definition at line 92 of file painttext.cpp.

References m_needLayout, and m_rect.

Referenced by Picker::draw(), NewButton::draw(), and StaticDisplay::setPaintTextRect().

93 {
94  if (m_rect != r) {
95  m_rect = r;
96  m_needLayout = true;
97  }
98 }
void PaintText::setText ( const std::string &  text)
virtual

Definition at line 101 of file painttext.cpp.

References i, m_needLayout, m_text, OLD_FORMAT_NEWLINE, and text().

Referenced by Picker::draw(), NewButton::draw(), PaintText(), and StaticDisplay::setText().

102 {
103  const string *finalText = &text;
104  string conversionResult;
105  if (text.find( OLD_FORMAT_NEWLINE ) != string::npos) {
106  //We have some old format characters we need to convert.
107  for (string::const_iterator i = text.begin(); i != text.end(); i++) {
108  if (*i == OLD_FORMAT_NEWLINE)
109  conversionResult.append( "#n#" );
110  else
111  conversionResult += (*i);
112  }
113  finalText = &conversionResult;
114  }
115  //OK, now we see whether anything has changed.
116  if (m_text != *finalText) {
117  m_text = *finalText;
118  m_needLayout = true;
119  }
120 }
void PaintText::setWidthExceeded ( WidthExceeded  w)
virtual

Definition at line 150 of file painttext.cpp.

References m_needLayout, and m_widthExceeded.

Referenced by StaticDisplay::setMultiLine().

151 {
152  if (m_widthExceeded != w) {
153  m_widthExceeded = w;
154  m_needLayout = true;
155  }
156 }
virtual const std::string& PaintText::text ( void  ) const
inlinevirtual

Definition at line 87 of file painttext.h.

References m_text.

Referenced by setText(), and StaticDisplay::text().

88  {
89  return m_text;
90  }
int PaintText::visibleLineCountStartingWith ( int  lineNumber,
float  vertInterval 
) const
virtual

Definition at line 166 of file painttext.cpp.

References calcLayoutIfNeeded(), i, LINE_HEIGHT_EPSILON, and m_lines.

Referenced by StaticDisplay::draw().

167 {
169  int result = 0;
170  float currentHeight = vertInterval;
171  for (vector< TextLine >::size_type i = lineNumber; i < m_lines.size(); ++i) {
172  const float lineHeight = m_lines[i].height;
173  if (currentHeight-lineHeight*LINE_HEIGHT_EPSILON < 0.0)
174  //Did all the lines.
175  break;
176  currentHeight -= lineHeight;
177  result++;
178  }
179  return result;
180 }
virtual WidthExceeded PaintText::widthExceeded ( void  ) const
inlinevirtual

Definition at line 123 of file painttext.h.

References m_widthExceeded.

Referenced by StaticDisplay::multiLine().

124  {
125  return m_widthExceeded;
126  }

Member Data Documentation

const size_t PaintText::END_LINE = 1000000
static

Definition at line 138 of file painttext.h.

GFXColor PaintText::m_color
protected

Definition at line 239 of file painttext.h.

Referenced by calcLayout(), color(), and setColor().

Font PaintText::m_font
protected

Definition at line 240 of file painttext.h.

Referenced by calcLayout(), font(), and setFont().

double PaintText::m_horizontalScaling
protected

Definition at line 248 of file painttext.h.

Referenced by calcLayout(), drawLines(), and lineInset().

Justification PaintText::m_justification
protected

Definition at line 241 of file painttext.h.

Referenced by justification(), lineInset(), and setJustification().

LayoutState PaintText::m_layout
protected
int PaintText::m_layoutVersion
protected

Definition at line 245 of file painttext.h.

Referenced by calcLayout(), and layoutVersion().

vector< TextLine > PaintText::m_lines
protected

Definition at line 246 of file painttext.h.

Referenced by calcLayout(), drawLines(), lineCount(), and visibleLineCountStartingWith().

bool PaintText::m_needLayout
protected
Rect PaintText::m_rect
protected

Definition at line 237 of file painttext.h.

Referenced by calcLayout(), drawLines(), lineInset(), rect(), and setRect().

std::string PaintText::m_text
protected
double PaintText::m_verticalScaling
protected

Definition at line 247 of file painttext.h.

Referenced by calcLayout(), and drawLines().

WidthExceeded PaintText::m_widthExceeded
protected

Definition at line 242 of file painttext.h.

Referenced by calcLayout(), setWidthExceeded(), and widthExceeded().


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