/************************************************************************* Return the number of lines the given text would be formatted to. *************************************************************************/ size_t Font::getFormattedLineCount(const String& text, const Rect& format_area, TextFormatting fmt, float x_scale) { // handle simple non-wrapped cases. if ((fmt == LeftAligned) || (fmt == Centred) || (fmt == RightAligned) || (fmt == Justified)) { return std::count(text.begin(), text.end(), static_cast<utf8>('\n')) + 1; } // handle wraping cases size_t lineStart = 0, lineEnd = 0; String sourceLine; float wrap_width = format_area.getWidth(); String whitespace = TextUtils::DefaultWhitespace; String thisLine, thisWord; size_t line_count = 0, currpos = 0; while (lineEnd < text.length()) { if ((lineEnd = text.find_first_of('\n', lineStart)) == String::npos) { lineEnd = text.length(); } sourceLine = text.substr(lineStart, lineEnd - lineStart); lineStart = lineEnd + 1; // get first word. currpos = getNextWord(sourceLine, 0, thisLine); // while there are words left in the string... while (String::npos != sourceLine.find_first_not_of(whitespace, currpos)) { // get next word of the string... currpos += getNextWord(sourceLine, currpos, thisWord); // if the new word would make the string too long if ((getTextExtent(thisLine, x_scale) + getTextExtent(thisWord, x_scale)) > wrap_width) { // too long, so that's another line of text line_count++; // remove whitespace from next word - it will form start of next line thisWord = thisWord.substr(thisWord.find_first_not_of(whitespace)); // reset for a new line. thisLine.clear(); } // add the next word to the line thisLine += thisWord; } // plus one for final line line_count++; } return line_count; }
/************************************************************************* Return the horizontal pixel extent given text would be formatted to. *************************************************************************/ float Font::getFormattedTextExtent(const String& text, const Rect& format_area, TextFormatting fmt, float x_scale) { float lineWidth; float widest = 0; size_t lineStart = 0, lineEnd = 0; String currLine; while (lineEnd < text.length()) { if ((lineEnd = text.find_first_of('\n', lineStart)) == String::npos) { lineEnd = text.length(); } currLine = text.substr(lineStart, lineEnd - lineStart); lineStart = lineEnd + 1; // +1 to skip \n char switch(fmt) { case Centred: case RightAligned: case LeftAligned: lineWidth = getTextExtent(currLine, x_scale); break; case Justified: // usually we use the width of the rect but we have to ensure the current line is not wider than that lineWidth = ceguimax(format_area.getWidth(), getTextExtent(currLine, x_scale)); break; case WordWrapLeftAligned: case WordWrapRightAligned: case WordWrapCentred: lineWidth = getWrappedTextExtent(currLine, format_area.getWidth(), x_scale); break; case WordWrapJustified: // same as above lineWidth = ceguimax(format_area.getWidth(), getWrappedTextExtent(currLine, format_area.getWidth(), x_scale)); break; default: throw InvalidRequestException("Font::getFormattedTextExtent - Unknown or unsupported TextFormatting value specified."); } if (lineWidth > widest) { widest = lineWidth; } } return widest; }
void CColoredStatic::repaint(CDC &dc) { CFont *font = GetFont(); if(font == NULL) { font = GetParent()->GetFont(); } CFont *oldFont = dc.SelectObject(font); if(m_bkColorSet) { dc.SetBkColor(m_bkColor); } dc.SetTextColor(m_textColor); String text = getWindowText(this); StringArray lineArray(Tokenizer(text, "\n")); const int textAlign = GetStyle() & 0x3; int y = 0; switch(textAlign) { case SS_LEFT: { for(size_t i = 0; i < lineArray.size(); i++) { const String &line = lineArray[i]; const CSize lineSize = getTextExtent(dc, line); dc.TextOut(0,y,line.cstr()); y += lineSize.cy; } } break; case SS_RIGHT: { const CSize winSize = getWindowSize(this); for(size_t i = 0; i < lineArray.size(); i++) { const String &line = lineArray[i]; const CSize lineSize = getTextExtent(dc, line); dc.TextOut(max(0, winSize.cx - lineSize.cx), y, line.cstr()); y += lineSize.cy; } } break; case SS_CENTER: { const CSize winSize = getWindowSize(this); for(size_t i = 0; i < lineArray.size(); i++) { const String &line = lineArray[i]; const CSize lineSize = getTextExtent(dc, line); dc.TextOut(max(0, (winSize.cx - lineSize.cx)/2), y, line.cstr()); y += lineSize.cy; } } break; } dc.SelectObject(oldFont); }
void SystemPainter::makeSpaceForText() { const int leftMargin = m_yAxisPainter->getMaxTextOffset() + 2; const int rightMargin = AbstractAxisPainter::ARROW_SIZE / 2; const int topMargin = AbstractAxisPainter::ARROW_SIZE / 2; const int bottomMargin = m_xAxisPainter->getMaxTextOffset() + getTextExtent(m_yAxisPainter->getMaxText()).cy + 1; Rectangle2D fr = getViewport().getFromRectangle(); const IntervalTransformation &xtr = getViewport().getXTransformation(); const IntervalTransformation &ytr = getViewport().getYTransformation(); bool adjustRectangle = false; if(xtr.isLinear() && fr.getMinX() == 0) { const double dx = -xtr.backwardTransform(getToRectangle().left + leftMargin); fr.m_x += dx; fr.m_w -= dx; adjustRectangle = true; } if(ytr.isLinear() && fr.getMinY() == 0) { const double dy = -ytr.backwardTransform(getToRectangle().top - bottomMargin); fr.m_y += dy; fr.m_h -= dy; adjustRectangle = true; } if(adjustRectangle) { getViewport().setFromRectangle(fr); } Rectangle2DR innerRectangle = getToRectangle(); innerRectangle.m_x += leftMargin; innerRectangle.m_w -= leftMargin + rightMargin; innerRectangle.m_y -= bottomMargin; innerRectangle.m_h += bottomMargin + topMargin; Point2D orig = innerRectangle.getProjection(Point2D(m_xAxisPainter->getAxisPoint(),m_yAxisPainter->getAxisPoint())); const double dx = min(orig.x - innerRectangle.m_x, leftMargin - getTextExtent(m_xAxisPainter->getMinText()).cx/2 - 1); const double dy = min(innerRectangle.m_y - orig.y, bottomMargin - getTextExtent(m_yAxisPainter->getMinText()).cy/2 - 1); if(dx > 0) { innerRectangle.m_x -= dx; innerRectangle.m_w += dx; } if(dy > 0) { innerRectangle.m_y += dy; innerRectangle.m_h -= dy; } m_origin = innerRectangle.getProjection(orig); }
/***************************************************** ** ** PdfPainter --- drawTextFormatted ** ******************************************************/ void PdfPainter::drawTextFormatted( const MRect &r, const wxString &t, const int& align ) { double oldx = pdf->GetX(); double oldy = pdf->GetY(); double x1 = r.x; double y1 = r.y; MPoint p = getTextExtent( t ); if ( align & Align::Top ) { y1 = r.y + p.imag(); } else if ( align & Align::Bottom ) { // add a certain part of p.imag, otherwise text will be too deep e.g. in SBC y1 = r.y + r.height - .2 * p.imag(); } else if ( align & Align::VCenter ) { y1 = r.y + .5 * ( r.height + p.imag() ); } if ( align & Align::HCenter ) { x1 = r.x + .5 * ( r.width - p.real() ); } else if ( align & Align::Right ) { x1 = r.x + r.width - p.real(); } pdf->Text( x1, y1, t ); //drawEllipse( x1, y1, 2, 2 ); pdf->SetXY( oldx, oldy ); }
/***************************************************** ** ** Painter --- getTextExtent ** ******************************************************/ MPoint Painter::getTextExtent( const MToken &token ) { const wxFont oldFont = getCurrentFont(); wxString s; Lang lang; SheetFormatter formatter( writercfg ); MPoint p; wxChar symbol = 0; SymbolProvider sp( writercfg ); switch ( token.entity ) { case TTSE_PLANET: if ( writercfg->planetSymbols ) symbol = sp.getPlanetCode( (ObjectId)token.entityId ); if ( ! symbol ) s = formatter.getObjectNamePlain( (ObjectId)token.entityId, token.textFormat, token.vedic ); break; case TTSE_SIGN: if ( writercfg->signSymbols ) symbol = sp.getSignCode( (Rasi)token.entityId ); if ( ! symbol ) s = lang.getSignName( (Rasi)token.entityId, token.textFormat ); //, writercfg->vedicSignNames ); break; case TTSE_ASPECT: symbol = SymbolProvider().getAspectCode( (ASPECT_TYPE)token.entityId ); if ( ! symbol ) s = AspectExpert::getAspectShortDescription( (int)token.entityId ); break; case TTSE_DIRECTION: symbol = sp.getRetroCode( (MOVING_DIRECTION)token.entityId ); if ( ! symbol ) s = wxT( "R" ); break; default: symbol = 0; s = token.text; break; } if ( symbol ) { const int pointSize = oldFont.GetPointSize(); setFont( *FontProvider::get()->getFontBySize( FONT_GRAPHIC_SYMBOLS, pointSize )); p = getTextExtent( symbol ); } else { p = getTextExtent( s ); } setFont( oldFont ); return p; }
/************************************************************************* draws wrapped text *************************************************************************/ size_t Font::drawWrappedText(const String& text, const Rect& draw_area, float z, const Rect& clip_rect, TextFormatting fmt, const ColourRect& colours, float x_scale, float y_scale) { size_t line_count = 0; Rect dest_area(draw_area); float wrap_width = draw_area.getWidth(); String whitespace = TextUtils::DefaultWhitespace; String thisLine, thisWord; size_t currpos = 0; // get first word. currpos += getNextWord(text, currpos, thisLine); // while there are words left in the string... while (String::npos != text.find_first_not_of(whitespace, currpos)) { // get next word of the string... currpos += getNextWord(text, currpos, thisWord); // if the new word would make the string too long if ((getTextExtent(thisLine, x_scale) + getTextExtent(thisWord, x_scale)) > wrap_width) { // output what we had until this new word line_count += drawText(thisLine, dest_area, z, clip_rect, fmt, colours, x_scale, y_scale); // remove whitespace from next word - it will form start of next line thisWord = thisWord.substr(thisWord.find_first_not_of(whitespace)); // reset for a new line. thisLine.clear(); // update y co-ordinate for next line dest_area.d_top += getLineSpacing(y_scale); } // add the next word to the line thisLine += thisWord; } // Last line is left aligned TextFormatting last_fmt = (fmt == Justified ? LeftAligned : fmt); // output last bit of string line_count += drawText(thisLine, dest_area, z, clip_rect, last_fmt, colours, x_scale, y_scale); return line_count; }
/***************************************************** ** ** Painter --- drawMString ** ******************************************************/ void Painter::drawMString( const MRect &r, MString &f, const int& align ) { #ifdef SHOW_STOP_WATCH static wxLongLong totaltime = 0; const wxLongLong starttime = wxGetLocalTimeMillis(); #endif static int count = 0; SheetFormatter sfmt; wxString s; if ( f.formattedLines.size() == 0 ) { if ( ! f.isEmpty() && f.size.real() == 0 ) { s = sfmt.fragment2PlainText( f ); //printf( "Painter::drawMString - old size %f %f\n", f.size.real(), f.size.imag()); f.size = getTextExtent( f ); printf( "Painter::drawMString - size not set #%d contents was %s, size now %f %f\n", count++, str2char( s ), f.size.real(), f.size.imag()); } drawSingleMStringLine( r, f, align ); //return; } else { double y0 = r.y; if ( align & Align::Top ) { // nothing } else if ( align & Align::Bottom ) { y0 = y0 + r.height - f.size.imag(); } else // default: align & align::VCenter { y0 += .5 * ( r.height - f.size.imag()); } MRect rect( r.x, y0, r.width, r.height ); int line = 0; for( list<MString>::iterator iter = f.formattedLines.begin(); iter != f.formattedLines.end(); iter++ ) { line++; rect.height = iter->size.imag(); //printf( " --->>> Line %d width %f h %f\n", line, iter->size.real(), iter->size.imag() ); drawSingleMStringLine( rect, *iter, align ); rect.y += rect.height; } } #ifdef SHOW_STOP_WATCH const wxLongLong duration = wxGetLocalTimeMillis() - starttime; totaltime += duration; wxLogMessage( wxString::Format( wxT( "Painter::drawTextFormatted in %ld msec, total %ld" ), duration.ToLong(), totaltime.ToLong() )); #endif }
CSize getTextExtent1(HDC hdc, const StringArray &a) { CSize result(0,0); for(size_t i = 0; i < a.size(); i++) { const CSize lineSize = getTextExtent(hdc, a[i]); result.cy += lineSize.cy; result.cx = max(result.cx, lineSize.cx); } return result; }
CSize getMaxTextExtent(HDC hdc, const StringArray &a) { CSize result(0,0); for(size_t i = 0; i < a.size(); i++) { const CSize sz = getTextExtent(hdc, a[i]); result.cx = max(result.cx, sz.cx); result.cy = max(result.cy, sz.cy); } return result; }
/************************************************************************* returns extent of widest line of wrapped text. *************************************************************************/ float Font::getWrappedTextExtent(const String& text, float wrapWidth, float x_scale) { String whitespace = TextUtils::DefaultWhitespace; String thisWord; size_t currpos; float lineWidth, wordWidth; float widest = 0; // get first word. currpos = getNextWord (text, 0, thisWord); lineWidth = getTextExtent (thisWord, x_scale); // while there are words left in the string... while (String::npos != text.find_first_not_of (whitespace, currpos)) { // get next word of the string... currpos += getNextWord (text, currpos, thisWord); wordWidth = getTextExtent (thisWord, x_scale); // if the new word would make the string too long if ((lineWidth + wordWidth) > wrapWidth) { if (lineWidth > widest) widest = lineWidth; // remove whitespace from next word - it will form start of next line thisWord = thisWord.substr (thisWord.find_first_not_of (whitespace)); wordWidth = getTextExtent (thisWord, x_scale); // reset for a new line. lineWidth = 0; } // add the next word to the line lineWidth += wordWidth; } if (lineWidth > widest) widest = lineWidth; return widest; }
/***************************************************** ** ** Painter --- getTextExtent ** ******************************************************/ MPoint Painter::getTextExtent( const MString &f ) { double x = 0, y = 0; MPoint p; for( list<MToken>::const_iterator iter = f.tokens.begin(); iter != f.tokens.end(); iter++ ) { p = getTextExtent( *iter ); x += p.real(); y = Max( y, p.imag()); } return MPoint( x, y ); }
/***************************************************** ** ** DcPainter --- drawRotatedText ** ******************************************************/ void DcPainter::drawRotatedText( wxString s, const double &x, const double &y, const double &alfa ) { MPoint p = getTextExtent( s ); /* const double a = 2; printf( "DcPainter::drawRotatedText angle is %f extent %f %f\n", alfa, p.real(), p.imag()); dc->DrawRectangle( x - .5 * p.real(), y - .5 * p.imag(), p.real(), p.imag()); dc->DrawRectangle( x - a, y - a, 2 * a, 2 * a ); */ const double w = .5 * p.real(); const double h = .5 * p.imag(); const double px = x - w * cos( alfa * DEG2RAD ) - h * sin( alfa * DEG2RAD ); const double py = y + w * sin( alfa * DEG2RAD ) - h * cos( alfa * DEG2RAD ); //dc->DrawRectangle( px - a, py - a, 2 * a, 2 * a ); dc->DrawRotatedText( s, px, py, alfa ); }
/***************************************************** ** ** PdfPainter --- drawRotatedText ** ******************************************************/ void PdfPainter::drawRotatedText( wxString s, const double &x, const double &y, const double &alfa ) { MPoint p = getTextExtent( s ); const double w = .5 * p.real(); const double h = .5 * p.imag(); // in pdf mode the anchor is located at the left sid of the text. y value is in the middle const double px = x - w * cos( alfa * DEG2RAD ) + h * sin( alfa * DEG2RAD ); const double py = y + w * sin( alfa * DEG2RAD ) + h * cos( alfa * DEG2RAD ); /* const int rw = 1; setDefaultPen(); //drawRectangle( x - rw, y - rw, 2 * rw, 2 * rw ); drawRectangle( px - rw, py - rw, 2 * rw, 2 * rw ); */ pdf->RotatedText( px, py, s, alfa ); }
//----------------------------------------------------------------------------- // Name: centerTextInArea // Desc: Calculates the location at which to begin rendering so that the text string // will render centered horizontally inside of the given area. //----------------------------------------------------------------------------- GUISize GUIFont::centerTextInArea(const char* text, int chars, const GUIRect* area, GUIPoint* renderPoint) const { // Calculate this text's area GUISize s; getTextExtent(text, chars, &s); // Center the text area in the rectangle int areaCenterX = (area->right + area->left) / 2; int areaCenterY = (area->bottom + area->top) / 2; int textCenterX = (s.width) / 2; int textCenterY = (s.height) / 2; renderPoint->x = areaCenterX - textCenterX; renderPoint->y = areaCenterY - textCenterY; return s; }
/************************************************************************* Draw a justified line of text. *************************************************************************/ void Font::drawTextLineJustified (const String& text, const Rect& draw_area, const Vector3& position, const Rect& clip_rect, const ColourRect& colours, float x_scale, float y_scale) { Vector3 cur_pos(position); const FontGlyph* glyph; float base_y = position.d_y; size_t char_count = text.length(); // Calculate the length difference between the justified text and the same text, left aligned // This space has to be shared between the space characters of the line float lost_space = getFormattedTextExtent(text, draw_area, Justified, x_scale) - getTextExtent(text, x_scale); // The number of spaces and tabs in the current line uint space_count = 0; size_t c; for (c = 0; c < char_count; ++c) if ((text[c] == ' ') || (text[c] == '\t')) ++space_count; // The width that must be added to each space character in order to transform the left aligned text in justified text float shared_lost_space = 0.0; if (space_count > 0) shared_lost_space = lost_space / (float)space_count; for (c = 0; c < char_count; ++c) { glyph = getGlyphData(text[c]); if (glyph) { const Image* img = glyph->getImage(); cur_pos.d_y = base_y - (img->getOffsetY() - img->getOffsetY() * y_scale); img->draw(cur_pos, glyph->getSize(x_scale, y_scale), clip_rect, colours); cur_pos.d_x += glyph->getAdvance(x_scale); // That's where we adjust the size of each space character if ((text[c] == ' ') || (text[c] == '\t')) cur_pos.d_x += shared_lost_space; } } }
//----[ wrapTextToWidth ]---------------------------------------------------- void GUIFont::wrapTextToWidth(char* text_buffer, int width) { char* line_start = text_buffer; char* space_after_last_word = text_buffer; char* read_point = text_buffer; while (*read_point != '\0') { // move to to the next word while (*read_point != '\0' && *read_point != ' ') { ++read_point; } // Swap in an endline to make getTextExtent work char old_ch = *read_point; *read_point = '\0'; // check the size of the word GUISize line_size; getTextExtent(line_start, -1, &line_size); *read_point = old_ch; // restore the read point character if (line_size.width >= width) { // too wide? if (space_after_last_word != line_start) { *space_after_last_word = '\n'; // turn the space into a carriage return *read_point = old_ch; // restore the character at the read point line_start = space_after_last_word + 1; // begin after last line space_after_last_word = line_start; while (*line_start == ' ') ++line_start; // skip spaces } else { // turn this location into a return, even though its past the line if (read_point != '\0') { *read_point = '\n'; line_start = read_point; } } read_point = line_start; // start reading } else { space_after_last_word = read_point; while (*read_point == ' ') ++read_point; // move up to the next word } } }
/***************************************************** ** ** PdfPainter --- drawSignSymbol ** ******************************************************/ void PdfPainter::drawSignSymbol( const int&x, const int &y, const int &sign, const int type, const int zoom, const double angle ) { Lang lang; double w, h; wxString s; if ( type == 2 ) s = textwriter->getSignName( sign, TSHORT ); else s = lang.getSignSymbolCode( sign, type ); getTextExtent( s, &w, &h ); /* setTransparentBrush(); setDefaultPen(); drawRectangle( x-3, y-3, 6, 6 ); drawRectangle( x-10, y-10, 20, 20 ); */ double x4 = x - .5 * w * cos( .25 * PI + angle * DEG2RAD ); double y4 = y + .5 * h * sin( .25 * PI + angle * DEG2RAD ); pdf->RotatedText( x4, y4, s, angle ); }
/***************************************************** ** ** PdfPainter --- drawTextFormatted ** ******************************************************/ void PdfPainter::drawTextFormatted( const double &x, const double &y, const double &w, const double &h, const wxString &t, const int& align ) { double sw, sh; double oldx = pdf->GetX(); double oldy = pdf->GetY(); double x1 = x; double y1 = y; pdf->SetXY( x, y1 ); getTextExtent( t, &sw, &sh ); if ( align & Align::Top ) { y1 = y + h; // + .5 * sh; } else if ( align & Align::Bottom ) { y1 = y + h; // + .5 * sh; } else if ( align & Align::VCenter ) { y1 = y + .5 * ( h + sh ); } if ( align & Align::HCenter ) { x1 = x + .5 * ( w - sw ); } else if ( align & Align::Right ) { x1 = x + w - sw; } pdf->Text( x1, y1, t ); //drawEllipse( x1, y1, 2, 2 ); pdf->SetXY( oldx, oldy ); }
/***************************************************** ** ** Painter --- drawSingleMStringLine ** ******************************************************/ void Painter::drawSingleMStringLine( const MRect &r, MString &f, const int& align ) { assert( f.formattedLines.size() == 0 ); wxString s; MPoint p; Lang lang( writercfg ); wxFont oldFont = getCurrentFont(); const int drawalign = Align::Left + Align::VCenter; SheetFormatter formatter( writercfg ); if ( ! f.isEmpty() && ( f.size.real() == 0 || f.size.imag() == 0 )) { printf( "WARN: size not set\n" ); f.size = getTextExtent( f ); } //printf( "PAINT -- --- - - - - x %f y %f w %f h %f SIZE x %f y %f\n", r.x, r.y, r.width, r.height, size.real(), size.imag() ); //printf( " ----- %s\n", str2char( formatter.fragment2PlainText( f ))); double x0 = r.x; double y0 = r.y; if ( align & Align::HCenter ) { x0 += .5 * ( r.width - f.size.real()); } else if ( align & Align::Right ) { x0 = x0 + r.width - f.size.real(); } // offset for subscriptum and superscriptum const double yoffset = .5 * f.size.imag(); double yy = y0; // + .5 * ( r.height - size.imag()); for( list<MToken>::const_iterator iter = f.tokens.begin(); iter != f.tokens.end(); iter++ ) { switch ( iter->fontFormat ) { case TTFF_SUBSCRPTUM: yy = y0 + yoffset; break; case TTFF_SUPERSCRPTUM: yy = y0 - yoffset; break; case TTFF_NORMAL: default: yy = y0; break; } setFont( oldFont ); wxChar symbol = 0; SymbolProvider sp( writercfg ); switch ( iter->entity ) { case TTSE_PLANET: if ( writercfg->planetSymbols ) symbol = sp.getPlanetCode( (ObjectId)iter->entityId ); if ( ! symbol || symbol == SYMBOL_CODE_ERROR ) s = formatter.getObjectNamePlain( (ObjectId)iter->entityId, iter->textFormat, iter->vedic ); break; case TTSE_SIGN: if ( writercfg->signSymbols ) symbol = sp.getSignCode( (Rasi)iter->entityId ); if ( ! symbol ) s = lang.getSignName( (Rasi)iter->entityId, iter->textFormat ); //, writercfg->vedicSignNames ); break; case TTSE_ASPECT: symbol = SymbolProvider().getAspectCode( (ASPECT_TYPE)iter->entityId ); if ( ! symbol ) s = AspectExpert::getAspectShortDescription( (int)iter->entityId ); break; case TTSE_DIRECTION: symbol = sp.getRetroCode( (MOVING_DIRECTION)iter->entityId ); if ( ! symbol ) s = wxT( "R" ); break; default: symbol = 0; s = iter->text; break; } if ( symbol && symbol != SYMBOL_CODE_ERROR ) { const int pointSize = oldFont.GetPointSize(); setFont( *FontProvider::get()->getFontBySize( FONT_GRAPHIC_SYMBOLS, pointSize )); drawTextFormatted( MRect( x0, yy, r.width, r.height ), symbol, drawalign ); p = getTextExtent( symbol ); } else { drawTextFormatted( MRect( x0, yy, r.width, r.height ), s, drawalign ); p = getTextExtent( s ); } x0 += p.real(); } }
CRect CHexViewView::updateSettings(CDC *dc) { CRect cr; GetClientRect(&cr); CFont *oldFont = NULL; if(dc == NULL) { dc = &m_workDC; oldFont = dc->SelectObject(&m_font); } m_readOnly = GetDocument()->isReadOnly(); m_radixFormat = m_settings->getRadixFormat(); m_asciiFormat = m_settings->getAsciiFormat(); m_byteSize = dc->GetTextExtent(m_settings->getDataSampleText()); m_charSize = dc->GetTextExtent(_T("0")); m_docSize = GetDocument()->getSize(); m_addrFormat.update(m_docSize, *m_settings); const bool showAddr = m_settings->getShowAddr(); const bool showAscii = m_settings->getShowAscii(); if(showAddr) { const String sampleText = m_addrFormat.getSampleText(); m_addrTextSize = getTextExtent(*dc,sampleText); } else { m_addrTextSize = CSize(0,0); } m_contentRect.left = m_addrTextSize.cx; m_contentRect.right = cr.right - m_byteSize.cx; m_contentRect.top = m_addrTextSize.cy; m_contentRect.bottom = cr.bottom - m_byteSize.cy; m_pageSize = CSize((m_contentRect.Width()-4) / m_byteSize.cx + 1, m_contentRect.Height()/m_byteSize.cy); if(m_settings->getFitLinesToWindow()) { m_lineSize = m_contentRect.Width()/m_byteSize.cx + 1; // Use windowsize to determine the number of bytes on each line } else { m_lineSize = m_settings->getLineSize(); } m_lineSize = max(m_lineSize, 1); // just to prevent division by zero. see below m_maxLineOffset = max(m_lineSize - m_pageSize.cx, 0); m_lineOffset = min(m_lineOffset, m_maxLineOffset); m_lineCount = (m_docSize - 1)/m_lineSize + 1; m_maxTopLine = max(m_lineCount - m_pageSize.cy, 0); m_topLine = min(m_topLine, m_maxTopLine); m_maxCaret = CPoint(m_pageSize.cx, m_pageSize.cy - 1); m_maxCaret.x = minMax(m_maxCaret.x, 0, (int)min(m_docSize, m_lineSize)); if(m_maxCaret.y >= m_lineCount) { m_maxCaret.y = (int)m_lineCount - 1; } if (m_maxCaret.y < 0) { m_maxCaret.y = 0; } m_lastLineSize = m_docSize % m_lineSize; if(m_lastLineSize == 0) { m_lastLineSize = m_lineSize; } m_maxLastLineOffset = min(m_lastLineSize - 1, m_maxLineOffset); if(m_readOnly || m_settings->getShowAscii()) { // readonly or ascii => only 0 is valid m_minDigitIndex = m_maxDigitIndex = 0; } else if((m_settings->getDataRadix() != 16)) { // dec or oct => [0..2] m_minDigitIndex = 0; m_maxDigitIndex = 2; } else if(m_settings->getHex3Pos()) { // hex 3-pos => [1..2] m_minDigitIndex = 1; m_maxDigitIndex = 2; } else { // hex 2-pos => [0..1] m_minDigitIndex = 0; m_maxDigitIndex = 1; } m_digitIndex = minMax(m_digitIndex, m_minDigitIndex, m_maxDigitIndex); if(dc == &m_workDC) { dc->SelectObject(oldFont); } return cr; }
/************************************************************************* Renders text on the display. Return number of lines output. *************************************************************************/ size_t Font::drawText(const String& text, const Rect& draw_area, float z, const Rect& clip_rect, TextFormatting fmt, const ColourRect& colours, float x_scale, float y_scale) { size_t thisCount; size_t lineCount = 0; float y_base = draw_area.d_top + getBaseline(y_scale); Rect tmpDrawArea( PixelAligned(draw_area.d_left), PixelAligned(draw_area.d_top), PixelAligned(draw_area.d_right), PixelAligned(draw_area.d_bottom) ); size_t lineStart = 0, lineEnd = 0; String currLine; while (lineEnd < text.length()) { if ((lineEnd = text.find_first_of('\n', lineStart)) == String::npos) lineEnd = text.length(); currLine = text.substr(lineStart, lineEnd - lineStart); lineStart = lineEnd + 1; // +1 to skip \n char switch(fmt) { case LeftAligned: drawTextLine(currLine, Vector3(tmpDrawArea.d_left, y_base, z), clip_rect, colours, x_scale, y_scale); thisCount = 1; y_base += getLineSpacing(y_scale); break; case RightAligned: drawTextLine(currLine, Vector3(tmpDrawArea.d_right - getTextExtent(currLine, x_scale), y_base, z), clip_rect, colours, x_scale, y_scale); thisCount = 1; y_base += getLineSpacing(y_scale); break; case Centred: drawTextLine(currLine, Vector3(PixelAligned(tmpDrawArea.d_left + ((tmpDrawArea.getWidth() - getTextExtent(currLine, x_scale)) / 2.0f)), y_base, z), clip_rect, colours, x_scale, y_scale); thisCount = 1; y_base += getLineSpacing(y_scale); break; case Justified: // new function in order to keep drawTextLine's signature unchanged drawTextLineJustified(currLine, draw_area, Vector3(tmpDrawArea.d_left, y_base, z), clip_rect, colours, x_scale, y_scale); thisCount = 1; y_base += getLineSpacing(y_scale); break; case WordWrapLeftAligned: thisCount = drawWrappedText(currLine, tmpDrawArea, z, clip_rect, LeftAligned, colours, x_scale, y_scale); tmpDrawArea.d_top += thisCount * getLineSpacing(y_scale); break; case WordWrapRightAligned: thisCount = drawWrappedText(currLine, tmpDrawArea, z, clip_rect, RightAligned, colours, x_scale, y_scale); tmpDrawArea.d_top += thisCount * getLineSpacing(y_scale); break; case WordWrapCentred: thisCount = drawWrappedText(currLine, tmpDrawArea, z, clip_rect, Centred, colours, x_scale, y_scale); tmpDrawArea.d_top += thisCount * getLineSpacing(y_scale); break; case WordWrapJustified: // no change needed thisCount = drawWrappedText(currLine, tmpDrawArea, z, clip_rect, Justified, colours, x_scale, y_scale); tmpDrawArea.d_top += thisCount * getLineSpacing(y_scale); break; default: throw InvalidRequestException("Font::drawText - Unknown or unsupported TextFormatting value specified."); } lineCount += thisCount; } // should not return 0 return ceguimax(lineCount, (size_t)1); }