Math::Vector2 SpriteFont::MeasureText(std::string text) { Math::Vector2 size(0, 0); Math::Vector2 pos(0, 0); char last = '\0'; for (int i = 0; i < text.length(); i++) { char c = text[i]; if (c != '\n') { pos.X += GetAdvanceX(c); } else { if (pos.X > size.X) size.X = pos.X; pos.X = 0; pos.Y += GetLineHeight(); } last = c; } if (pos.X > size.X) size.X = pos.X; size.Y = pos.Y + GetLineHeight(); return size; }
void wxListBox::UpdateItems() { // only refresh the items which must be refreshed if ( m_updateCount == -1 ) { // refresh all wxLogTrace(_T("listbox"), _T("Refreshing all")); Refresh(); } else { wxSize size = GetClientSize(); wxRect rect; rect.width = size.x; rect.height = size.y; rect.y += m_updateFrom*GetLineHeight(); rect.height = m_updateCount*GetLineHeight(); // we don't need to calculate x position as we always refresh the // entire line(s) CalcScrolledPosition(0, rect.y, NULL, &rect.y); wxLogTrace(_T("listbox"), _T("Refreshing items %d..%d (%d-%d)"), m_updateFrom, m_updateFrom + m_updateCount - 1, rect.GetTop(), rect.GetBottom()); Refresh(true, &rect); } }
float CglFont::GetTextHeight_(const std::u8string& text, float* descender, int* numLines) { if (text.empty()) { if (descender) *descender = 0.0f; if (numLines) *numLines = 0; return 0.0f; } float h = 0.0f, d = GetLineHeight() + GetDescender(); unsigned int multiLine = 1; int pos = 0; while (pos < text.length()) { const char32_t u = Utf8GetNextChar(text, pos); switch(u) { // inlined colorcode case ColorCodeIndicator: pos = SkipColorCodes(text, pos - 1); if (pos<0) { pos = text.length(); } break; // reset color case ColorResetIndicator: break; // newline case 0x0d: // CR+LF if (pos < text.length() && text[pos] == 0x0a) ++pos; case 0x0a: // LF multiLine++; d = GetLineHeight() + GetDescender(); break; // printable char default: const GlyphInfo& g = GetGlyph(u); if (g.descender < d) d = g.descender; if (multiLine < 2 && g.height > h) h = g.height; // only calc height for the first line } } if (multiLine>1) d -= (multiLine-1) * GetLineHeight(); if (descender) *descender = d; if (numLines) *numLines = multiLine; return h; }
void wxListBox::DoDraw(wxControlRenderer *renderer) { // adjust the DC to account for scrolling wxDC& dc = renderer->GetDC(); PrepareDC(dc); dc.SetFont(GetFont()); // get the update rect wxRect rectUpdate = GetUpdateClientRect(); int yTop, yBottom; CalcUnscrolledPosition(0, rectUpdate.GetTop(), NULL, &yTop); CalcUnscrolledPosition(0, rectUpdate.GetBottom(), NULL, &yBottom); // get the items which must be redrawn wxCoord lineHeight = GetLineHeight(); size_t itemFirst = yTop / lineHeight, itemLast = (yBottom + lineHeight - 1) / lineHeight, itemMax = m_strings->GetCount(); if ( itemFirst >= itemMax ) return; if ( itemLast > itemMax ) itemLast = itemMax; // do draw them wxLogTrace(_T("listbox"), _T("Repainting items %d..%d"), itemFirst, itemLast); DoDrawRange(renderer, itemFirst, itemLast); }
void wxListBox::DoEnsureVisible(int n) { if ( !m_showScrollbarY ) { // nothing to do - everything is shown anyhow return; } int first; GetViewStart(0, &first); if ( first > n ) { // we need to scroll upwards, so make the current item appear on top // of the shown range Scroll(0, n); } else { int last = first + GetClientSize().y / GetLineHeight() - 1; if ( last < n ) { // scroll down: the current item appears at the bottom of the // range Scroll(0, n - (last - first)); } } }
void CEditView::GetCharBoundingRect( int nCol, int nRow, LPRECT prcChar ) const { int nViewCol = m_pBuffer->ConvertBufferColToViewCol( nRow, nCol ); int cyLine = GetLineHeight(); prcChar->top = m_rcAll.top + ( nRow - GetTopIndex() ) * cyLine; prcChar->bottom = prcChar->top + cyLine; int cxChar = GetCharWidth(); prcChar->left = m_rcAll.left + GetLeftMargin( TRUE, TRUE ) + ( nViewCol - GetLeftIndex() ) * cxChar; // for tabs, we want to expand the rect to represent the entire expanded width, not just one char's worth int cbChar = m_pBuffer->GetCharSize( nRow, nCol ); prcChar->right = prcChar->left + cxChar * ( m_pBuffer->ConvertBufferColToViewCol( nRow, nCol + cbChar ) - nViewCol ); }
void wxListBox::UpdateScrollbars() { wxSize size = GetClientSize(); // is our height enough to show all items? int nLines = GetCount(); wxCoord lineHeight = GetLineHeight(); bool showScrollbarY = nLines*lineHeight > size.y; // check the width too if required wxCoord charWidth, maxWidth; bool showScrollbarX; if ( HasHorzScrollbar() ) { charWidth = GetCharWidth(); maxWidth = GetMaxWidth(); showScrollbarX = maxWidth > size.x; } else // never show it { charWidth = maxWidth = 0; showScrollbarX = false; } // what should be the scrollbar range now? int scrollRangeX = showScrollbarX ? (maxWidth + charWidth - 1) / charWidth + 2 // FIXME : 0; int scrollRangeY = showScrollbarY ? nLines + (size.y % lineHeight + lineHeight - 1) / lineHeight : 0; // reset scrollbars if something changed: either the visibility status // or the range of a scrollbar which is shown if ( (showScrollbarY != m_showScrollbarY) || (showScrollbarX != m_showScrollbarX) || (showScrollbarY && (scrollRangeY != m_scrollRangeY)) || (showScrollbarX && (scrollRangeX != m_scrollRangeX)) ) { int x, y; GetViewStart(&x, &y); SetScrollbars(charWidth, lineHeight, scrollRangeX, scrollRangeY, x, y); m_showScrollbarX = showScrollbarX; m_showScrollbarY = showScrollbarY; m_scrollRangeX = scrollRangeX; m_scrollRangeY = scrollRangeY; } }
void ChatWindow::Draw() { SPADES_MARK_FUNCTION(); float winX = 4.f; float winY = killfeed ? 8.f : (float)renderer->ScreenHeight() * .5f; std::list<ChatEntry>::iterator it; float lHeight = GetLineHeight(); float y = firstY; Vector4 shadowColor = {0, 0, 0, 0.5}; for(it = entries.begin(); it != entries.end(); it++){ ChatEntry& ent = *it; std::string msg = ent.msg; Vector4 color = GetColor(MsgColorRestore); float tx = 0.f, ty = y; float fade = ent.fade; if(ent.timeFade < 1.f) fade *= ent.timeFade; shadowColor.w = .5f * fade; color.w *= fade; for(size_t i = 0; i < msg.size(); i++){ if(msg[i] == 13 || msg[i] == 10){ tx = 0.f; ty += lHeight; }else if(msg[i] <= MsgColorMax){ color = GetColor(msg[i]); color.w *= fade; }else{ std::string ch(&msg[i], 1); font->Draw(ch, MakeVector2(tx + winX + 1.f, ty + winY + 1.f), 1.f, shadowColor); font->Draw(ch, MakeVector2(tx + winX, ty + winY), 1.f, color); tx += font->Measure(ch).x; } } y += ent.height; } }
Text::Text(FontCache* fc) { cache = fc; buffer = NULL; bufferAlpha = NULL; bufferW = bufferH = 0; statesL = 0; PushState(); SetFont(fc->GetDefaultFont()); SetFontSize(DEFAULT_FONT_SIZE); penX = marginLeft; penY = marginTop + GetLineHeight(); }
wxSize wxVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int maxHeight ) { int height = 250; maxHeight -= 2; // Must take borders into account if ( m_strings.GetCount() ) { if ( prefHeight > 0 ) height = prefHeight; if ( height > maxHeight ) height = maxHeight; int totalHeight = GetTotalHeight(); // + 3; // Take borders into account on Mac or scrollbars always appear #if defined(__WXMAC__) totalHeight += 2; #endif if ( height >= totalHeight ) { height = totalHeight; } else { // Adjust height to a multiple of the height of the first item // NB: Calculations that take variable height into account // are unnecessary. int fih = GetLineHeight(0); height -= height % fih; } } else height = 50; CalcWidths(); // Take scrollbar into account in width calculations int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); return wxSize(minWidth > widestWidth ? minWidth : widestWidth, height+2); }
int CUrlRichEditCtrl::FindUrlEx(const CPoint& point) { int nUrl = m_aUrls.GetSize(); while (nUrl--) { const URLITEM& urli = m_aUrls[nUrl]; CRect rUrl(GetCharPos(urli.cr.cpMin), GetCharPos(urli.cr.cpMax)); rUrl.bottom += GetLineHeight(); if (rUrl.PtInRect(point)) return nUrl; } // not found return -1; }
void wxListBox::DoSetSize(int x, int y, int width, int height, int sizeFlags) { if ( GetWindowStyle() & wxLB_INT_HEIGHT ) { // we must round up the height to an entire number of rows // the client area must contain an int number of rows, so take borders // into account wxRect rectBorders = GetRenderer()->GetBorderDimensions(GetBorder()); wxCoord hBorders = rectBorders.y + rectBorders.height; wxCoord hLine = GetLineHeight(); height = ((height - hBorders + hLine - 1) / hLine)*hLine + hBorders; } wxListBoxBase::DoSetSize(x, y, width, height, sizeFlags); }
void CCrystalEditView::ShowDropIndicator(const CPoint &point) { if (! m_bDropPosVisible) { HideCursor(); m_ptSavedCaretPos = GetCursorPos(); m_bDropPosVisible = TRUE; ::CreateCaret(m_hWnd, (HBITMAP) 1, 2, GetLineHeight()); } m_ptDropPos = ClientToText(point); if (m_ptDropPos.x >= m_nOffsetChar) { SetCaretPos(TextToClient(m_ptDropPos)); ShowCaret(); } else { HideCaret(); } }
void FGameplayDebuggerCanvasContext::Print(const FColor& Color, const FString& String) { FTaggedStringParser Parser(Color); Parser.ParseString(String); const float LineHeight = GetLineHeight(); for (int32 NodeIdx = 0; NodeIdx < Parser.NodeList.Num(); NodeIdx++) { const FTaggedStringParser::FNode& NodeData = Parser.NodeList[NodeIdx]; if (NodeData.bNewLine) { if (Canvas.IsValid() && (CursorY + LineHeight) > Canvas->ClipY) { DefaultX += Canvas->ClipX / 2; CursorY = 0.0f; } CursorX = DefaultX; CursorY += LineHeight; } if (NodeData.String.Len() > 0) { float SizeX = 0.0f, SizeY = 0.0f; MeasureString(NodeData.String, SizeX, SizeY); FCanvasTextItem TextItem(FVector2D::ZeroVector, FText::FromString(NodeData.String), Font.Get(), FLinearColor(NodeData.Color)); if (FontRenderInfo.bEnableShadow) { TextItem.EnableShadow(FColor::Black, FVector2D(1, 1)); } DrawItem(TextItem, CursorX, CursorY); CursorX += SizeX; } } MoveToNewLine(); }
/* calc the pixel width and maximum pixel height for a given section */ void kGUIText::GetSubSize(int sstart,int slen,unsigned int *pixwidth,unsigned int *pixheight) { unsigned int width; unsigned int height; unsigned int maxheight; kGUIFace *face=0; unsigned int size; unsigned int *qw=0; unsigned int ch; /* current character */ unsigned int nb; /* number of bytes for current character */ /* optimize: two loops one for rich and one for plain */ width=0; if(GetUseRichInfo()==false) { /* plain mode, single font and size for whole string */ maxheight=GetLineHeight(); if(slen) { face=kGUIFont::GetFace(GetFontID()); size=GetFontSize(); kGUI::SelectFont(face,size); qw=face->GetQuickWidths(size); width=0; while(slen>0) { ch=GetChar(sstart,&nb); //assert(ch!=0,"reading past end of string!"); sstart+=nb; slen-=nb; if(ch=='\t') { int tw; tw=GetTabWidth(width); if(!tw) { /* use space width if no defined tabs */ if(qw && ' '<MAXCCACHE) width+=qw[' ']; else width+=face->GetCharWidth(' '); } width+=tw; } else { if(qw && ch<MAXCCACHE) width+=qw[ch]; else width+=face->GetCharWidth(ch); width+=m_letterspacing; } } } } else { /* rich string, can have diff font and size on each character */ maxheight=0; if(slen) { RICHINFO_DEF *ri; unsigned int lastfontid=0; size=0; while(slen>0) { ri=GetRichInfoPtr(sstart); if((ri->fontid!=lastfontid) || (ri->fontsize!=size)) { size=ri->fontsize; lastfontid=ri->fontid; face=kGUIFont::GetFace(lastfontid); kGUI::SelectFont(face,size); qw=face->GetQuickWidths(size); height=face->GetPixHeight(size); if(height>maxheight) maxheight=height; } ch=GetChar(sstart,&nb); assert(ch!=0,"reading past end of string!"); sstart+=nb; slen-=nb; if(ch=='\t') { int tw; tw=GetTabWidth(width); if(!tw) { /* use space width if no defined tabs */ if(qw && ' '<MAXCCACHE) width+=qw[' ']; else width+=face->GetCharWidth(' '); } width+=tw; } else { if(qw && ch<MAXCCACHE) width+=qw[ch]; else width+=face->GetCharWidth(ch); width+=m_letterspacing; } } } } if(pixwidth) pixwidth[0]=width; if(pixheight) pixheight[0]=maxheight; }
void ChatWindow::AddMessage(const std::string &msg){ SPADES_MARK_FUNCTION(); ChatEntry ent; // get visible message string std::string str; float x = 0.f, maxW = GetWidth(); float lh = GetLineHeight(), h = lh; size_t wordStart = std::string::npos; size_t wordStartOutPos; for(size_t i = 0; i < msg.size(); i++){ if(msg[i] > MsgColorMax && msg[i] != 13 && msg[i] != 10){ if(isWordChar(msg[i])){ if(wordStart == std::string::npos){ wordStart = msg.size(); wordStartOutPos = str.size(); } }else{ wordStart = std::string::npos; } float w = font->Measure(std::string(&msg[i],1)).x; if(x + w > maxW){ if(wordStart != std::string::npos && wordStart != str.size()){ // adding a part of word. // do word wrapping std::string s = msg.substr(wordStart, i - wordStart + 1); float nw = font->Measure(s).x; if(nw <= maxW){ // word wrap succeeds w = nw; x = w; h += lh; str.insert(wordStartOutPos, "\n"); goto didWordWrap; } } x = 0; h += lh; str += 13; } x += w; str += msg[i]; didWordWrap:; }else if(msg[i] == 13 || msg[i] == 10){ x = 0; h += lh; str += 13; }else{ str += msg[i]; } } ent.height = h; ent.msg = msg; ent.fade = 0.f; ent.timeFade = 15.f; entries.push_front(ent); firstY -= h; }
void CTextWrap::WrapTextConsole(std::list<word>& words, float maxWidth, float maxHeight) { if (words.empty() || (GetLineHeight()<=0.0f)) return; const bool splitAllWords = false; const unsigned int maxLines = (unsigned int)std::floor(std::max(0.0f, maxHeight / GetLineHeight())); line* currLine; word linebreak; linebreak.isLineBreak = true; bool addEllipsis = false; bool currLineValid = false; // true if there was added any data to the current line std::list<word>::iterator wi = words.begin(); std::list<line> lines; lines.push_back(line()); currLine = &(lines.back()); currLine->start = words.begin(); for (; ;) { currLineValid = true; if (wi->isLineBreak) { currLine->forceLineBreak = true; currLine->end = wi; // start a new line after the '\n' lines.push_back(line()); currLineValid = false; currLine = &(lines.back()); currLine->start = wi; ++currLine->start; } else { currLine->width += wi->width; currLine->end = wi; if (currLine->width > maxWidth) { currLine->width -= wi->width; // line grew too long by adding the last word, insert a LineBreak const bool splitLastWord = (wi->width > (0.5 * maxWidth)); const float freeWordSpace = (maxWidth - currLine->width); if (splitAllWords || splitLastWord) { // last word W is larger than 0.5 * maxLineWidth, split it into // get 'L'eft and 'R'ight parts of the split (wL becomes Left, *wi becomes R) bool restart = (currLine->start == wi); // turns *wi into R word wL = SplitWord(*wi, freeWordSpace); if (splitLastWord && wL.width == 0.0f) { // With smart splitting it can happen that the word isn't split at all, // this can cause a race condition when the word is longer than maxWidth. // In this case we have to force an unaesthetic split. wL = SplitWord(*wi, freeWordSpace, false); } // increase by the width of the L-part of *wi currLine->width += wL.width; // insert the L-part right before R wi = words.insert(wi, wL); if (restart) currLine->start = wi; ++wi; } // insert the forced linebreak (either after W or before R) linebreak.pos = wi->pos; currLine->end = words.insert(wi, linebreak); while (wi != words.end() && wi->isSpace) wi = words.erase(wi); lines.push_back(line()); currLineValid = false; currLine = &(lines.back()); currLine->start = wi; --wi; // compensate the wi++ downwards } } ++wi; if (wi == words.end()) { break; } if (lines.size() > maxLines) { addEllipsis = true; break; } } // empty row if (!currLineValid || (currLine->start == words.end() && !currLine->forceLineBreak)) { lines.pop_back(); currLine = &(lines.back()); } // if we had to cut the text because of missing space, add an ellipsis if (addEllipsis) AddEllipsis(lines, words, maxWidth); wi = currLine->end; ++wi; wi = words.erase(wi, words.end()); }
CBSurface *CBFontTT::RenderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { TextLineList lines; WrapText(text, width, maxHeight, lines); TextLineList::iterator it; int textHeight = lines.size() * (m_MaxCharHeight + m_Ascender); SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); SDL_LockSurface(surface); int posY = (int)GetLineHeight() - (int)m_Descender; for (it = lines.begin(); it != lines.end(); ++it) { TextLine *line = (*it); int posX = 0; switch (align) { case TAL_CENTER: posX += (width - line->GetWidth()) / 2; break; case TAL_RIGHT: posX += width - line->GetWidth(); break; } textOffset = 0; for (size_t i = 0; i < line->GetText().length(); i++) { wchar_t ch = line->GetText()[i]; GlyphInfo *glyph = m_GlyphCache->GetGlyph(ch); if (!glyph) continue; textOffset = std::max(textOffset, glyph->GetBearingY()); } int origPosX = posX; wchar_t prevChar = L'\0'; for (size_t i = 0; i < line->GetText().length(); i++) { wchar_t ch = line->GetText()[i]; GlyphInfo *glyph = m_GlyphCache->GetGlyph(ch); if (!glyph) continue; float kerning = 0; if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); posX += (int)kerning; if (glyph->GetBearingY() > 0) { int i = 10; } SDL_Rect rect; rect.x = posX + glyph->GetBearingX(); rect.y = posY - glyph->GetBearingY() + textOffset; rect.w = glyph->GetImage()->w; rect.h = glyph->GetImage()->h; BlitSurface(glyph->GetImage(), surface, &rect); prevChar = ch; posX += (int)(glyph->GetAdvanceX()); posY += (int)(glyph->GetAdvanceY()); } if (m_IsUnderline) { for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { Uint8 *buf = (Uint8 *)surface->pixels + (int)(m_UnderlinePos + m_Ascender) * surface->pitch; Uint32 *buf32 = (Uint32 *)buf; buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); } } SDL_UnlockSurface(surface); delete line; line = NULL; posY += GetLineHeight(); } CBSurfaceSDL *wmeSurface = new CBSurfaceSDL(Game); if (SUCCEEDED(wmeSurface->CreateFromSDLSurface(surface))) { SDL_FreeSurface(surface); return wmeSurface; } else { SDL_FreeSurface(surface); delete wmeSurface; return NULL; } }
RenderQueue* BREW::CreateFrameDrawable( SharedPtr<const Frame> frame ) const { sf::Color border_color( GetProperty<sf::Color>( "BorderColor", frame ) ); sf::Color color( GetProperty<sf::Color>( "Color", frame ) ); sf::Color background_color( GetProperty<sf::Color>( "BackgroundColor", frame ) ); float border_width( GetProperty<float>( "BorderWidth", frame ) ); const std::string& font_name( GetProperty<std::string>( "FontName", frame ) ); unsigned int font_size( GetProperty<unsigned int>( "FontSize", frame ) ); const sf::Font& font( *GetResourceManager().GetFont( font_name ) ); float label_padding( GetProperty<float>( "LabelPadding", frame ) ); float line_height = GetLineHeight( font, font_size ); RenderQueue* queue( new RenderQueue ); // Right queue->Add( Renderer::Get().CreateLine( sf::Vector2f( frame->GetAllocation().width - border_width, line_height / 2.f ), sf::Vector2f( frame->GetAllocation().width - border_width, frame->GetAllocation().height - border_width ), border_color, border_width ) ); // Bottom queue->Add( Renderer::Get().CreateLine( sf::Vector2f( frame->GetAllocation().width, frame->GetAllocation().height - border_width ), sf::Vector2f( 0.f, frame->GetAllocation().height - border_width ), border_color, border_width ) ); // Left queue->Add( Renderer::Get().CreateLine( sf::Vector2f( 0.f, frame->GetAllocation().height - border_width ), sf::Vector2f( 0.f, line_height / 2.f ), border_color, border_width ) ); float label_start_x = line_height; float label_end_x = line_height; float alignment = frame->GetAlignment().x; if( frame->GetLabel().getSize() > 0 ) { sf::Vector2f metrics = GetTextMetrics( frame->GetLabel(), font, font_size ); metrics.x += ( 2 * label_padding ); label_start_x += ( alignment * ( frame->GetAllocation().width - 2 * line_height - metrics.x ) ); label_end_x += ( metrics.x + alignment * ( frame->GetAllocation().width - 2 * line_height - metrics.x ) ); sf::Text text( frame->GetLabel(), font, font_size ); text.setPosition( label_start_x + label_padding, .0f ); text.setColor( color ); queue->Add( Renderer::Get().CreateText( text, background_color ) ); } // Top Left queue->Add( Renderer::Get().CreateLine( sf::Vector2f( 0.f, line_height / 2.f ), sf::Vector2f( label_start_x, line_height / 2.f ), border_color, border_width ) ); // Top Right queue->Add( Renderer::Get().CreateLine( sf::Vector2f( label_end_x, line_height / 2.f ), sf::Vector2f( frame->GetAllocation().width - border_width, line_height / 2.f ), border_color, border_width ) ); return queue; }
int CBFontTT::GetLetterHeight() { return GetLineHeight(); }
const float Text::GetHeight() const { return GetLineHeight() * mNumLines; }
void CglFont::RenderString(float x, float y, const float& scaleX, const float& scaleY, const std::string& str) { /** * NOTE: * Font rendering does not use display lists, but VAs. It's actually faster * (450% faster with a 7600GT!) for these reasons: * * 1. When using DLs, we can not group multiple glyphs into one glBegin/End pair * because glTranslatef can not go between such a pair. * 2. We can now eliminate all glPushMatrix/PopMatrix pairs related to font rendering * because the transformations are calculated on the fly. These are just a couple of * floating point multiplications and shouldn't be too expensive. */ const float startx = x; const float lineHeight_ = scaleY * GetLineHeight(); unsigned int length = (unsigned int)str.length(); const std::u8string& ustr = toustring(str); va.EnlargeArrays(length * 4, 0, VA_SIZE_2DT); int skippedLines; bool colorChanged; const GlyphInfo* g = NULL; float4 newColor = textColor; char32_t c; int i = 0; do { const bool endOfString = SkipColorCodesAndNewLines(ustr, &i, &newColor, &colorChanged, &skippedLines, &baseTextColor); if (endOfString) return; c = Utf8GetNextChar(str,i); if (colorChanged) { if (autoOutlineColor) { SetColors(&newColor,NULL); } else { SetTextColor(&newColor); } } const GlyphInfo* c_g = &GetGlyph(c); if (skippedLines>0) { x = startx; y -= skippedLines * lineHeight_; } else if (g) { x += scaleX * GetKerning(*g, *c_g); } g = c_g; const auto& tc = g->texCord; const float dx0 = (scaleX * g->size.x0()) + x, dy0 = (scaleY * g->size.y0()) + y; const float dx1 = (scaleX * g->size.x1()) + x, dy1 = (scaleY * g->size.y1()) + y; va.AddVertexQ2dT(dx0, dy1, tc.x0(), tc.y1()); va.AddVertexQ2dT(dx0, dy0, tc.x0(), tc.y0()); va.AddVertexQ2dT(dx1, dy0, tc.x1(), tc.y0()); va.AddVertexQ2dT(dx1, dy1, tc.x1(), tc.y1()); } while(true); }
void CglFont::RenderStringOutlined(float x, float y, const float& scaleX, const float& scaleY, const std::string& str) { const float shiftX = (scaleX/fontSize) * GetOutlineWidth(), shiftY = (scaleY/fontSize) * GetOutlineWidth(); const float startx = x; const float lineHeight_ = scaleY * GetLineHeight(); const std::u8string& ustr = toustring(str); const size_t length = str.length(); va.EnlargeArrays(length * 4, 0, VA_SIZE_2DT); va2.EnlargeArrays(length * 4, 0, VA_SIZE_2DT); int skippedLines; bool colorChanged; const GlyphInfo* g = NULL; float4 newColor = textColor; char32_t c; int i = 0; do { const bool endOfString = SkipColorCodesAndNewLines(ustr, &i, &newColor, &colorChanged, &skippedLines, &baseTextColor); if (endOfString) return; c = Utf8GetNextChar(str,i); if (colorChanged) { if (autoOutlineColor) { SetColors(&newColor,NULL); } else { SetTextColor(&newColor); } } const GlyphInfo* c_g = &GetGlyph(c); if (skippedLines>0) { x = startx; y -= skippedLines * lineHeight_; } else if (g) { x += scaleX * GetKerning(*g, *c_g); } g = c_g; const auto& tc = g->texCord; const auto& stc = g->shadowTexCord; const float dx0 = (scaleX * g->size.x0()) + x, dy0 = (scaleY * g->size.y0()) + y; const float dx1 = (scaleX * g->size.x1()) + x, dy1 = (scaleY * g->size.y1()) + y; // draw outline va2.AddVertexQ2dT(dx0-shiftX, dy1-shiftY, stc.x0(), stc.y1()); va2.AddVertexQ2dT(dx0-shiftX, dy0+shiftY, stc.x0(), stc.y0()); va2.AddVertexQ2dT(dx1+shiftX, dy0+shiftY, stc.x1(), stc.y0()); va2.AddVertexQ2dT(dx1+shiftX, dy1-shiftY, stc.x1(), stc.y1()); // draw the actual character va.AddVertexQ2dT(dx0, dy1, tc.x0(), tc.y1()); va.AddVertexQ2dT(dx0, dy0, tc.x0(), tc.y0()); va.AddVertexQ2dT(dx1, dy0, tc.x1(), tc.y0()); va.AddVertexQ2dT(dx1, dy1, tc.x1(), tc.y1()); } while(true); }
int Text::WrapString(const char* string, bool draw) { lineBreaksL = 0; int from = 0; int to = strlen(string); int lineOffset = 0; int visibleLines = -1; const int maxWidth = bufferW - marginLeft - marginRight - 1; const int spaceW = cache->GetAdvance(' '); const int lineHeight = GetLineHeight(); if (maxWidth < spaceW) { return lineBreaksL = 1; } bool panic = false; int line = 0; int lineWidth = penX - marginLeft; int wordCount = 0; int charCount = 0; int lineDrawEnd = 0; int lastPenX = penX; int lastPenY = penY; int index = from; char tempString[to - from + 1]; int tempIndex = 0; int lastFittingChar = 0; //Last char that fits on the current line bool allCharsDrawn = true; while (index < to) { //Find next word start while (index < to && INVISIBLE_CHAR(string[index])) { //Skip whitespace index++; if (line >= lineOffset && (visibleLines < 0 || line - lineOffset < visibleLines)) { charCount++; } } int oldIndex = index; int oldCharCount = charCount; int ww = 0; //Word Width (includes optional prefixed space) bool wordFits = true; bool newlineEncountered = false; if (index < to) { if (wordCount > 0) { ww = spaceW; tempString[tempIndex] = ' '; tempIndex++; } lastFittingChar = tempIndex; //Last char that fits on the current line //Add letters to word while (index < to && !INVISIBLE_CHAR(string[index])) { if (string[index] == '\n' || string[index] == '|') { index++; lastFittingChar = index; newlineEncountered = true; wordFits = false; panic = false; //Word fits break; } u32 c = string[index]; int bytes = FontCache::GetCodePoint(string + index, &c); if (bytes == 0) bytes = 1; int advance = cache->GetAdvance(c); if (lineWidth + ww + advance <= maxWidth) { //Char still fits on this line lastFittingChar += bytes; } else if (ww + advance > maxWidth) { //This single word is wider than an entire line. It needs to be //cut on an unnatural position to be displayed. wordFits = false; //Word will never fit in this state break; } else { ww = 9999; break; } for (int n = 0; n < bytes; n++) { tempString[tempIndex] = string[index]; tempIndex++; index++; } if (line >= lineOffset && (visibleLines < 0 || line - lineOffset < visibleLines)) { charCount++; } if (visibleChars < 0 || charCount <= visibleChars) { lineDrawEnd = tempIndex; } else { allCharsDrawn = (visibleChars < 0); } ww += advance; } } if (!wordFits || (index >= to && lineWidth + ww <= maxWidth)) { //if !wordFits :: Word longer than a full line, cut up word //if index >= to :: Add final word to line tempIndex = lastFittingChar + 1; lineWidth += ww; } else if (lineWidth + ww > maxWidth) { tempIndex -= (index - oldIndex); lineDrawEnd = MIN(lineDrawEnd, tempIndex); charCount = oldCharCount; index = oldIndex; wordFits = false; } if (!wordFits || index >= to) { //Word doesn't fit on the current line or the end of the string //has been reached if (lineDrawEnd <= 0 && !newlineEncountered) { break; } lineBreaks[line] = index; //Draw Line if (line >= lineOffset && (visibleLines < 0 || line - lineOffset < visibleLines)) { tempString[lineDrawEnd] = '\0'; if (draw) { PrintLine(tempString); } else { CalcLine(tempString); } lastPenX = penX; lastPenY = penY; penX = marginLeft; penY += lineHeight; //Cursor shouldn't go back after a hard newline if (newlineEncountered) { lastPenX = penX; lastPenY = penY; } } int oldLineDrawEnd = lineDrawEnd; //New Line line++; lineWidth = penX - marginLeft; lineDrawEnd = 0; wordCount = 0; tempIndex = 0; if (oldLineDrawEnd == 0) { //Can't even fit a single char two times in a row, time to quit if (panic) { break; } else { panic = true; } } else { panic = false; } } else { //Add word to line wordCount++; lineWidth += ww; } } penX = lastPenX; penY = lastPenY; lineBreaksL = MAX(1, line); return lineBreaksL; }
void CShaderEdit::OnUpdate() { if(m_nIDEvent == -1) { m_nIDEvent = SetTimer(1, 100, NULL); } CString text; int nStartChar = 0, nEndChar = -1; GetSel(nStartChar, nEndChar); if(nStartChar == nEndChar) { GetWindowText(text); while(nStartChar > 0 && _istalnum(text.GetAt(nStartChar-1))) nStartChar--; } if(nStartChar < nEndChar) { text = text.Mid(nStartChar, nEndChar - nStartChar); text.TrimRight('('); text.MakeLower(); m_acdlg.m_list.ResetContent(); CString key, value; POSITION pos = m_acdlg.m_inst.GetStartPosition(); while(pos) { POSITION cur = pos; m_acdlg.m_inst.GetNextAssoc(pos, key, value); if(key.Find(text) == 0) { CAtlList<CString> sl; Explode(value, sl, '|', 2); if(sl.GetCount() != 2) continue; CString name = sl.RemoveHead(); CString description = sl.RemoveHead(); int i = m_acdlg.m_list.AddString(name); m_acdlg.m_list.SetItemDataPtr(i, cur); } } if(m_acdlg.m_list.GetCount() > 0) { int lineheight = GetLineHeight(); CPoint p = PosFromChar(nStartChar); p.y += lineheight; ClientToScreen(&p); CRect r(p, CSize(100, 100)); m_acdlg.MoveWindow(r); m_acdlg.SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); m_acdlg.ShowWindow(SW_SHOWNOACTIVATE); m_nEndChar = nEndChar; return; } } m_acdlg.ShowWindow(SW_HIDE); }
void Text::PrintNewline() { penX = marginLeft; penY += GetLineHeight(); }
int kGUIText::CalcLineList(int w) { unsigned int line; unsigned int sindex; unsigned int totalchars; unsigned int numfit; unsigned int pixwidth; unsigned int maxw; const unsigned char *t; const unsigned char *cc; const unsigned char *ce; kGUIInputLineInfo *lbptr; if(m_linelist.GetNumEntries()==0) { m_linelist.Init(1,-1); m_linelist.SetEntry(0,new kGUIInputLineInfo); } maxw=0; line=0; sindex=0; t=(const unsigned char *)GetString(); totalchars=GetLen(); if((!t) || (!totalchars)) { lbptr=m_linelist.GetEntry(0); lbptr->startindex=sindex; lbptr->endindex=sindex; lbptr->pixwidth=0; lbptr->hardbreak=true; lbptr->pixheight=GetLineHeight(); m_lltotalheight=lbptr->pixheight+2; lbptr->ty=0; lbptr->by=m_lltotalheight-1; m_llnum=1; return(0); } m_lltotalheight=0; do{ numfit=CalcFitWidth(sindex,totalchars-sindex,w,&pixwidth); if(pixwidth>maxw) maxw=pixwidth; /* go back and break on a space, unless there are no spaces */ if(!numfit) { if(t[sindex]!=10) /* supposed to be a blank line? */ numfit=totalchars-sindex; /* rest of line */ } else { cc=t+sindex; ce=cc+numfit; if(ce[0]!=10 && ce[0]) { while((ce[-1]!=' ') && (ce>cc)) --ce; if(ce!=cc) /* only if a space was found */ numfit=(int)(ce-cc); } } /* alloc more space? */ if(line>=m_linelist.GetNumEntries()) m_linelist.Alloc(line<<3); lbptr=m_linelist.GetEntry(line); if(!lbptr) { lbptr=new kGUIInputLineInfo; m_linelist.SetEntry(line,lbptr); } lbptr->startindex=sindex; /* line starts at this character */ lbptr->endindex=sindex+numfit; /* line stops at this character */ /* calc size of Substring */ lbptr->ty=m_lltotalheight; GetSubSize(sindex,numfit,&lbptr->pixwidth,&lbptr->pixheight); if(!numfit) { /* how tall is a blank line, use height of last character in previous line */ if(!sindex) lbptr->pixheight=GetLineHeight(); else GetSubSize(sindex-1,1,0,&lbptr->pixheight); } m_lltotalheight+=lbptr->pixheight+2; lbptr->by=m_lltotalheight-1; if(t[sindex+numfit]==0 || t[sindex+numfit]==10) lbptr->hardbreak=true; else lbptr->hardbreak=false; ++line; sindex+=numfit; if(t[sindex]==10) ++sindex; else if(!numfit) break; }while(sindex<totalchars); m_llnum=line; return(maxw); }
void kGUIText::Draw(int x,int y,int w,int h,kGUIColor color) { /* this is the only draw call that looks at the valign and halign */ kGUIInputLineInfo *lbptr; int i; FT_HALIGN halign=GetHAlign(); int cx=0; int cy; int lineheight=GetLineHeight()+2; int numl; if(m_llnum<2) numl=1; else numl=m_llnum; cy=y; switch(GetVAlign()) { case FT_TOP: break; case FT_MIDDLE: cy+=(h-((lineheight*numl)-2))/2; break; case FT_BOTTOM: cy+=h-((lineheight*numl)-2); break; } if(m_llnum<2) { switch(halign) { case FT_LEFT: cx=x; break; case FT_CENTER: cx=x+((w-(int)GetWidth())/2); break; case FT_RIGHT: cx=x+(w-(int)GetWidth()); break; } DrawSection(0,GetLen(),x,cx,cy,GetLineHeight(),color); } else { for(i=0;i<m_llnum;++i) { lbptr=m_linelist.GetEntry(i); switch(halign) { case FT_LEFT: cx=x; break; case FT_CENTER: cx=x+((w-lbptr->pixwidth)/2); break; case FT_RIGHT: cx=x+(w-lbptr->pixwidth); break; } DrawSection(lbptr->startindex,lbptr->endindex-lbptr->startindex,x,cx,cy,lbptr->pixheight,color); cy+=lineheight; } } }