//----------------------------------------------------------------------------// void FalagardEditbox::renderTextBidi(const WidgetLookFeel& wlf, const String& text, const Rectf& text_area, float text_offset) { #ifdef CEGUI_BIDI_SUPPORT const Font* const font = d_window->getFont(); // setup initial rect for text formatting Rectf text_part_rect(text_area); // allow for scroll position text_part_rect.d_min.d_x += text_offset; // centre text vertically within the defined text area text_part_rect.d_min.d_y += (text_area.getHeight() - font->getFontHeight()) * 0.5f; ColourRect colours; const float alpha_comp = d_window->getEffectiveAlpha(); // get unhighlighted text colour (saves accessing property twice) ColourRect unselectedColour; setColourRectToUnselectedTextColour(unselectedColour); // see if the editbox is active or inactive. Editbox* const w = static_cast<Editbox*>(d_window); const bool active = editboxIsFocussed(); if (w->getSelectionLength() == 0) { // no highlighted text - we can draw the whole thing colours = unselectedColour; colours.modulateAlpha(alpha_comp); text_part_rect.d_min.d_x = font->drawText(w->getGeometryBuffer(), text, text_part_rect.getPosition(), &text_area, colours); } else { // there is highlighted text - because of the Bidi support - the // highlighted area can be in some cases nonconsecutive. // So - we need to draw it char by char (I guess we can optimize it more // but this is not that big performance hit because it only happens if // we have highlighted text - not that common...) for (size_t i = 0 ; i < text.size() ; i++) { // get the char String currChar = text.substr(i, 1); size_t realPos = 0; // get he visual pos of the char if (w->getBidiVisualMapping()->getV2lMapping().size() > i) { realPos = w->getBidiVisualMapping()->getV2lMapping()[i]; } // check if it is in the highlighted region bool highlighted = realPos >= w->getSelectionStartIndex() && realPos < w->getSelectionStartIndex() + w->getSelectionLength(); float charAdvance = font->getGlyphData(currChar[0])->getAdvance(1.0f); if (highlighted) { setColourRectToSelectedTextColour(colours); colours.modulateAlpha(alpha_comp); { // calculate area for selection imagery. Rectf hlarea(text_area); hlarea.d_min.d_x = text_part_rect.d_min.d_x ; hlarea.d_max.d_x = text_part_rect.d_min.d_x + charAdvance ; // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection"). render(*w, hlarea, 0, &text_area); } } else { colours = unselectedColour; colours.modulateAlpha(alpha_comp); } font->drawText(w->getGeometryBuffer(), currChar, text_part_rect.getPosition(), &text_area, colours); // adjust rect for next section text_part_rect.d_min.d_x += charAdvance; } } #endif }
void FalagardMultiLineEditbox::cacheTextLines(const Rectf& dest_area) { MultiLineEditbox* w = (MultiLineEditbox*)d_window; // text is already formatted, we just grab the lines and render them with the required alignment. Rectf drawArea(dest_area); float vertScrollPos = w->getVertScrollbar()->getScrollPosition(); drawArea.offset(Vector2f(-w->getHorzScrollbar()->getScrollPosition(), -vertScrollPos)); const Font* fnt = w->getFont(); if (fnt) { // calculate final colours to use. ColourRect colours; const float alpha = w->getEffectiveAlpha(); ColourRect normalTextCol; setColourRectToUnselectedTextColour(normalTextCol); normalTextCol.modulateAlpha(alpha); ColourRect selectTextCol; setColourRectToSelectedTextColour(selectTextCol); selectTextCol.modulateAlpha(alpha); ColourRect selectBrushCol; w->hasInputFocus() ? setColourRectToActiveSelectionColour(selectBrushCol) : setColourRectToInactiveSelectionColour(selectBrushCol); selectBrushCol.modulateAlpha(alpha); const MultiLineEditbox::LineList& d_lines = w->getFormattedLines(); const size_t numLines = d_lines.size(); // calculate the range of visible lines size_t sidx,eidx; sidx = static_cast<size_t>(vertScrollPos / fnt->getLineSpacing()); eidx = 1 + sidx + static_cast<size_t>(dest_area.getHeight() / fnt->getLineSpacing()); eidx = ceguimin(eidx, numLines); drawArea.d_min.d_y += fnt->getLineSpacing()*static_cast<float>(sidx); // for each formatted line. for (size_t i = sidx; i < eidx; ++i) { Rectf lineRect(drawArea); const MultiLineEditbox::LineInfo& currLine = d_lines[i]; String lineText(w->getTextVisual().substr(currLine.d_startIdx, currLine.d_length)); // offset the font little down so that it's centered within its own spacing const float old_top = lineRect.top(); lineRect.d_min.d_y += (fnt->getLineSpacing() - fnt->getFontHeight()) * 0.5f; // if it is a simple 'no selection area' case if ((currLine.d_startIdx >= w->getSelectionEndIndex()) || ((currLine.d_startIdx + currLine.d_length) <= w->getSelectionStartIndex()) || (w->getSelectionBrushImage() == 0)) { colours = normalTextCol; // render the complete line. fnt->drawText(w->getGeometryBuffer(), lineText, lineRect.getPosition(), &dest_area, colours); } // we have at least some selection highlighting to do else { // Start of actual rendering section. String sect; size_t sectIdx = 0, sectLen; float selStartOffset = 0.0f, selAreaWidth = 0.0f; // render any text prior to selected region of line. if (currLine.d_startIdx < w->getSelectionStartIndex()) { // calculate length of text section sectLen = w->getSelectionStartIndex() - currLine.d_startIdx; // get text for this section sect = lineText.substr(sectIdx, sectLen); sectIdx += sectLen; // get the pixel offset to the beginning of the selection area highlight. selStartOffset = fnt->getTextAdvance(sect); // draw this portion of the text colours = normalTextCol; fnt->drawText(w->getGeometryBuffer(), sect, lineRect.getPosition(), &dest_area, colours); // set position ready for next portion of text lineRect.d_min.d_x += selStartOffset; } // calculate the length of the selected section sectLen = ceguimin(w->getSelectionEndIndex() - currLine.d_startIdx, currLine.d_length) - sectIdx; // get the text for this section sect = lineText.substr(sectIdx, sectLen); sectIdx += sectLen; // get the extent to use as the width of the selection area highlight selAreaWidth = fnt->getTextAdvance(sect); const float text_top = lineRect.top(); lineRect.top(old_top); // calculate area for the selection brush on this line lineRect.left(drawArea.left() + selStartOffset); lineRect.right(lineRect.left() + selAreaWidth); lineRect.bottom(lineRect.top() + fnt->getLineSpacing()); // render the selection area brush for this line colours = selectBrushCol; w->getSelectionBrushImage()->render(w->getGeometryBuffer(), lineRect, &dest_area, colours); // draw the text for this section colours = selectTextCol; fnt->drawText(w->getGeometryBuffer(), sect, lineRect.getPosition(), &dest_area, colours); lineRect.top(text_top); // render any text beyond selected region of line if (sectIdx < currLine.d_length) { // update render position to the end of the selected area. lineRect.d_min.d_x += selAreaWidth; // calculate length of this section sectLen = currLine.d_length - sectIdx; // get the text for this section sect = lineText.substr(sectIdx, sectLen); // render the text for this section. colours = normalTextCol; fnt->drawText(w->getGeometryBuffer(), sect, lineRect.getPosition(), &dest_area, colours); } } // update master position for next line in paragraph. drawArea.d_min.d_y += fnt->getLineSpacing(); } } }
//----------------------------------------------------------------------------// void FalagardEditbox::renderTextNoBidi(const WidgetLookFeel& wlf, const String& text, const Rectf& text_area, float text_offset) { const Font* font = d_window->getFont(); // setup initial rect for text formatting Rectf text_part_rect(text_area); // allow for scroll position text_part_rect.d_min.d_x += text_offset; // centre text vertically within the defined text area text_part_rect.d_min.d_y += (text_area.getHeight() - font->getFontHeight()) * 0.5f; ColourRect colours; const float alpha_comp = d_window->getEffectiveAlpha(); // get unhighlighted text colour (saves accessing property twice) ColourRect unselectedColours; setColourRectToUnselectedTextColour(unselectedColours); // see if the editbox is active or inactive. Editbox* const w = static_cast<Editbox*>(d_window); const bool active = editboxIsFocussed(); if (w->getSelectionLength() != 0) { // calculate required start and end offsets of selection imagery. float selStartOffset = font->getTextAdvance(text.substr(0, w->getSelectionStartIndex())); float selEndOffset = font->getTextAdvance(text.substr(0, w->getSelectionEndIndex())); // calculate area for selection imagery. Rectf hlarea(text_area); hlarea.d_min.d_x += text_offset + selStartOffset; hlarea.d_max.d_x = hlarea.d_min.d_x + (selEndOffset - selStartOffset); // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection"). render(*w, hlarea, 0, &text_area); } // draw pre-highlight text String sect = text.substr(0, w->getSelectionStartIndex()); colours = unselectedColours; colours.modulateAlpha(alpha_comp); text_part_rect.d_min.d_x = font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &text_area, colours); // draw highlight text sect = text.substr(w->getSelectionStartIndex(), w->getSelectionLength()); setColourRectToSelectedTextColour(colours); colours.modulateAlpha(alpha_comp); text_part_rect.d_min.d_x = font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &text_area, colours); // draw post-highlight text sect = text.substr(w->getSelectionEndIndex()); colours = unselectedColours; colours.modulateAlpha(alpha_comp); font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &text_area, colours); }