void ImagerySection::render(Window& srcWindow, const Rectf& baseRect, const CEGUI::ColourRect* modColours, const Rectf* clipper, bool clipToDisplay) const { // decide what to do as far as colours go ColourRect finalCols; initMasterColourRect(srcWindow, finalCols); if (modColours) finalCols *= *modColours; ColourRect* finalColsPtr = (finalCols.isMonochromatic() && finalCols.d_top_left.getARGB() == 0xFFFFFFFF) ? 0 : &finalCols; // render all frame components in this section for(FrameList::const_iterator frame = d_frames.begin(); frame != d_frames.end(); ++frame) { (*frame).render(srcWindow, baseRect, finalColsPtr, clipper, clipToDisplay); } // render all image components in this section for(ImageryList::const_iterator image = d_images.begin(); image != d_images.end(); ++image) { (*image).render(srcWindow, baseRect, finalColsPtr, clipper, clipToDisplay); } // render all text components in this section for(TextList::const_iterator text = d_texts.begin(); text != d_texts.end(); ++text) { (*text).render(srcWindow, baseRect, finalColsPtr, clipper, clipToDisplay); } }
void SectionSpecification::render(Window& srcWindow, float base_z, const ColourRect* modcols, const Rect* clipper, bool clipToDisplay) const { // see if we need to bother rendering if (d_renderControlProperty.empty() || PropertyHelper::stringToBool(srcWindow.getProperty(d_renderControlProperty))) { try { // get the imagery section object with the name we're set up to use const ImagerySection* sect = &WidgetLookManager::getSingleton().getWidgetLook(d_owner).getImagerySection(d_sectionName); // decide what colours are to be used ColourRect finalColours; initColourRectForOverride(srcWindow, finalColours); finalColours.modulateAlpha(srcWindow.getEffectiveAlpha()); if (modcols) finalColours *= *modcols; // render the imagery section sect->render(srcWindow, base_z, &finalColours, clipper, clipToDisplay); } // do nothing here, errors are non-faltal and are logged for debugging purposes. catch (Exception&) {} } }
//----------------------------------------------------------------------------// void FalagardEditbox::setColourRectToOptionalPropertyColour( const String& propertyName, ColourRect& colour_rect) const { if (d_window->isPropertyPresent(propertyName)) colour_rect = PropertyHelper<ColourRect>::fromString( d_window->getProperty(propertyName)); else colour_rect.setColours(0); }
//----------------------------------------------------------------------------// void FalagardMultiLineEditbox::setColourRectToOptionalPropertyColour( const String& propertyName, ColourRect& colour_rect) const { if (d_window->isPropertyPresent(propertyName)) colour_rect = d_window->getProperty<ColourRect>(propertyName); else colour_rect.setColours(0); }
void FalagardEditbox::populateRenderCache() { const StateImagery* imagery; // draw container etc // get WidgetLookFeel for the assigned look. const WidgetLookFeel& wlf = WidgetLookManager::getSingleton().getWidgetLook(d_lookName); // try and get imagery for the approprite state. imagery = &wlf.getStateImagery(isDisabled() ? "Disabled" : (isReadOnly() ? "ReadOnly" : "Enabled")); // peform the rendering operation for the container. imagery->render(*this); // get destination area for text const Rect textArea(wlf.getNamedArea("TextArea").getArea().getPixelRect(*this)); // // Required preliminary work for text rendering operations // const Font* font = getFont(); // no font == no more rendering if (!font) return; // This will point to the final string to be used for rendering. Useful because it means we // do not have to have duplicate code or be copying d_text for handling masked/unmasked text. String* editText; // Create a 'masked' version of the string if needed. String maskedText; if (isTextMasked()) { maskedText.insert(0, d_text.length(), getMaskCodePoint()); editText = &maskedText; } // text not masked to editText will be the windows d_text String. else { editText = &d_text; } // calculate best position to render text to ensure carat is always visible float textOffset; float extentToCarat = font->getTextExtent(editText->substr(0, getCaratIndex())); // get carat imagery const ImagerySection& caratImagery = wlf.getImagerySection("Carat"); // store carat width float caratWidth = caratImagery.getBoundingRect(*this, textArea).getWidth(); // if box is inactive if (!hasInputFocus()) { textOffset = d_lastTextOffset; } // if carat is to the left of the box else if ((d_lastTextOffset + extentToCarat) < 0) { textOffset = -extentToCarat; } // if carat is off to the right. else if ((d_lastTextOffset + extentToCarat) >= (textArea.getWidth() - caratWidth)) { textOffset = textArea.getWidth() - extentToCarat - caratWidth; } // else carat is already within the box else { textOffset = d_lastTextOffset; } ColourRect colours; float alpha_comp = getEffectiveAlpha(); // // Draw label text // // setup initial rect for text formatting Rect text_part_rect(textArea); // allow for scroll position text_part_rect.d_left += textOffset; // centre text vertically within the defined text area text_part_rect.d_top += (textArea.getHeight() - font->getLineSpacing()) * 0.5f; // draw pre-highlight text String sect = editText->substr(0, getSelectionStartIndex()); colours.setColours(d_normalTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw highlight text sect = editText->substr(getSelectionStartIndex(), getSelectionLength()); colours.setColours(d_selectTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw post-highlight text sect = editText->substr(getSelectionEndIndex()); colours.setColours(d_normalTextColour); colours.modulateAlpha(alpha_comp); d_renderCache.cacheText(sect, font, LeftAligned, text_part_rect, 0, colours, &textArea); // remember this for next time. d_lastTextOffset = textOffset; // see if the editbox is active or inactive. bool active = (!isReadOnly()) && hasInputFocus(); // // Render selection imagery. // if (getSelectionLength() != 0) { // calculate required start and end offsets of selection imagery. float selStartOffset = font->getTextExtent(editText->substr(0, getSelectionStartIndex())); float selEndOffset = font->getTextExtent(editText->substr(0, getSelectionEndIndex())); // calculate area for selection imagery. Rect hlarea(textArea); hlarea.d_left += textOffset + selStartOffset; hlarea.d_right = hlarea.d_left + (selEndOffset - selStartOffset); // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection").render(*this, hlarea, 0, &textArea); } // // Render carat // if (active) { Rect caratRect(textArea); caratRect.d_left += extentToCarat + textOffset; caratImagery.render(*this, caratRect, 0, 0, &textArea); } }
/************************************************************************* Render text lines. *************************************************************************/ void MultiLineEditbox::cacheTextLines(const Rect& dest_area) { // text is already formatted, we just grab the lines and render them with the required alignment. Rect drawArea(dest_area); drawArea.offset(Point(-d_horzScrollbar->getScrollPosition(), -d_vertScrollbar->getScrollPosition())); Renderer* renderer = System::getSingleton().getRenderer(); const Font* fnt = getFont(); if (fnt) { // get layers to use for rendering float textZ = renderer->getZLayer(4) - renderer->getCurrentZ(); float selZ = renderer->getZLayer(3) - renderer->getCurrentZ(); // calculate final colours to use. ColourRect colours; float alpha = getEffectiveAlpha(); colour normalTextCol = d_normalTextColour; normalTextCol.setAlpha(normalTextCol.getAlpha() * alpha); colour selectTextCol = d_selectTextColour; selectTextCol.setAlpha(selectTextCol.getAlpha() * alpha); colour selectBrushCol = hasInputFocus() ? d_selectBrushColour : d_inactiveSelectBrushColour; selectBrushCol.setAlpha(selectBrushCol.getAlpha() * alpha); // Cache font info const float fLineSpacing = fnt->getLineSpacing (); // for each formatted line. for (size_t i = 0; i < d_lines.size(); ++i) { Rect lineRect(drawArea); // Check line is within the dest_area if ( lineRect.d_top < dest_area.d_bottom && lineRect.d_top + fLineSpacing > dest_area.d_top ) { const LineInfo& currLine = d_lines[i]; String lineText(d_text.substr(currLine.d_startIdx, currLine.d_length)); // if it is a simple 'no selection area' case if ((currLine.d_startIdx >= d_selectionEnd) || ((currLine.d_startIdx + currLine.d_length) <= d_selectionStart) || (d_selectionBrush == NULL)) { colours.setColours(normalTextCol); // render the complete line. d_renderCache.cacheText(lineText, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); } // 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 < d_selectionStart) { // calculate length of text section sectLen = d_selectionStart - 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->getTextExtent(sect); // draw this portion of the text colours.setColours(normalTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); // set position ready for next portion of text lineRect.d_left += selStartOffset; } // calculate the length of the selected section sectLen = ceguimin(d_selectionEnd - 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->getTextExtent(sect); // draw the text for this section colours.setColours(selectTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); // 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_left += 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.setColours(normalTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); } // calculate area for the selection brush on this line lineRect.d_left = drawArea.d_left + selStartOffset; lineRect.d_right = lineRect.d_left + selAreaWidth; lineRect.d_bottom = lineRect.d_top + fLineSpacing; // render the selection area brush for this line colours.setColours(selectBrushCol); d_renderCache.cacheImage(*d_selectionBrush, lineRect, selZ, colours, &dest_area); } } // update master position for next line in paragraph. drawArea.d_top += fLineSpacing; } } }
void FrameComponent::render_impl(Window& srcWindow, Rect& destRect, float base_z, const CEGUI::ColourRect* modColours, const Rect* clipper, bool clipToDisplay) const { Rect backgroundRect(destRect); Rect finalRect; Size imageSize; ColourRect imageColours; float leftfactor, rightfactor, topfactor, bottomfactor; bool calcColoursPerImage; // vars we use to track what to do with the side pieces. float topOffset = 0, bottomOffset = 0, leftOffset = 0, rightOffset = 0; float topWidth, bottomWidth, leftHeight, rightHeight; topWidth = bottomWidth = destRect.getWidth(); leftHeight = rightHeight = destRect.getHeight(); // calculate final overall colours to be used ColourRect finalColours; initColoursRect(srcWindow, modColours, finalColours); if (finalColours.isMonochromatic()) { calcColoursPerImage = false; imageColours = finalColours; } else { calcColoursPerImage = true; } // top-left image if (d_frameImages[FIC_TOP_LEFT_CORNER]) { // calculate final destination area imageSize = d_frameImages[FIC_TOP_LEFT_CORNER]->getSize(); finalRect.d_left = destRect.d_left; finalRect.d_top = destRect.d_top; finalRect.setSize(imageSize); // update adjustments required to edges do to presence of this element. topOffset += imageSize.d_width; leftOffset += imageSize.d_height; topWidth -= topOffset; leftHeight -= leftOffset; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_TOP_LEFT_CORNER]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_TOP_LEFT_CORNER]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_TOP_LEFT_CORNER], finalRect, base_z, imageColours, 0, clipToDisplay); } // top-right image if (d_frameImages[FIC_TOP_RIGHT_CORNER]) { // calculate final destination area imageSize = d_frameImages[FIC_TOP_RIGHT_CORNER]->getSize(); finalRect.d_left = destRect.d_right - imageSize.d_width; finalRect.d_top = destRect.d_top; finalRect.setSize(imageSize); // update adjustments required to edges do to presence of this element. rightOffset += imageSize.d_height; topWidth -= imageSize.d_width; rightHeight -= rightOffset; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_TOP_RIGHT_CORNER]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_TOP_RIGHT_CORNER]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_TOP_RIGHT_CORNER], finalRect, base_z, imageColours, 0, clipToDisplay); } // bottom-left image if (d_frameImages[FIC_BOTTOM_LEFT_CORNER]) { // calculate final destination area imageSize = d_frameImages[FIC_BOTTOM_LEFT_CORNER]->getSize(); finalRect.d_left = destRect.d_left; finalRect.d_top = destRect.d_bottom - imageSize.d_height; finalRect.setSize(imageSize); // update adjustments required to edges do to presence of this element. bottomOffset += imageSize.d_width; bottomWidth -= bottomOffset; leftHeight -= imageSize.d_height; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_BOTTOM_LEFT_CORNER]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_BOTTOM_LEFT_CORNER]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_BOTTOM_LEFT_CORNER], finalRect, base_z, imageColours, 0, clipToDisplay); } // bottom-right image if (d_frameImages[FIC_BOTTOM_RIGHT_CORNER]) { // calculate final destination area imageSize = d_frameImages[FIC_BOTTOM_RIGHT_CORNER]->getSize(); finalRect.d_left = destRect.d_right - imageSize.d_width; finalRect.d_top = destRect.d_bottom - imageSize.d_height; finalRect.setSize(imageSize); // update adjustments required to edges do to presence of this element. bottomWidth -= imageSize.d_width; rightHeight -= imageSize.d_height; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_BOTTOM_RIGHT_CORNER]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_BOTTOM_RIGHT_CORNER]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_BOTTOM_RIGHT_CORNER], finalRect, base_z, imageColours, 0, clipToDisplay); } // top image if (d_frameImages[FIC_TOP_EDGE]) { // calculate final destination area imageSize = d_frameImages[FIC_TOP_EDGE]->getSize(); finalRect.d_left = destRect.d_left + topOffset; finalRect.d_right = finalRect.d_left + topWidth; finalRect.d_top = destRect.d_top; finalRect.d_bottom = finalRect.d_top + imageSize.d_height; // adjust background area to miss this edge backgroundRect.d_top += imageSize.d_height + d_frameImages[FIC_TOP_EDGE]->getOffsetY();; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_TOP_EDGE]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_TOP_EDGE]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_TOP_EDGE], finalRect, base_z, imageColours, 0, clipToDisplay); } // bottom image if (d_frameImages[FIC_BOTTOM_EDGE]) { // calculate final destination area imageSize = d_frameImages[FIC_BOTTOM_EDGE]->getSize(); finalRect.d_left = destRect.d_left + bottomOffset; finalRect.d_right = finalRect.d_left + bottomWidth; finalRect.d_bottom = destRect.d_bottom; finalRect.d_top = finalRect.d_bottom - imageSize.d_height; // adjust background area to miss this edge backgroundRect.d_bottom -= imageSize.d_height - d_frameImages[FIC_BOTTOM_EDGE]->getOffsetY();; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_BOTTOM_EDGE]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_BOTTOM_EDGE]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_BOTTOM_EDGE], finalRect, base_z, imageColours, 0, clipToDisplay); } // left image if (d_frameImages[FIC_LEFT_EDGE]) { // calculate final destination area imageSize = d_frameImages[FIC_LEFT_EDGE]->getSize(); finalRect.d_left = destRect.d_left; finalRect.d_right = finalRect.d_left + imageSize.d_width; finalRect.d_top = destRect.d_top + leftOffset; finalRect.d_bottom = finalRect.d_top + leftHeight; // adjust background area to miss this edge backgroundRect.d_left += imageSize.d_width + d_frameImages[FIC_LEFT_EDGE]->getOffsetX(); // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_LEFT_EDGE]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_LEFT_EDGE]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_LEFT_EDGE], finalRect, base_z, imageColours, 0, clipToDisplay); } // right image if (d_frameImages[FIC_RIGHT_EDGE]) { // calculate final destination area imageSize = d_frameImages[FIC_RIGHT_EDGE]->getSize(); finalRect.d_top = destRect.d_top + rightOffset; finalRect.d_bottom = finalRect.d_top + rightHeight; finalRect.d_right = destRect.d_right; finalRect.d_left = finalRect.d_right - imageSize.d_width; // adjust background area to miss this edge backgroundRect.d_right -= imageSize.d_width - d_frameImages[FIC_RIGHT_EDGE]->getOffsetX(); // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.d_left + d_frameImages[FIC_RIGHT_EDGE]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.d_top + d_frameImages[FIC_RIGHT_EDGE]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. srcWindow.getRenderCache().cacheImage(*d_frameImages[FIC_RIGHT_EDGE], finalRect, base_z, imageColours, 0, clipToDisplay); } if (d_frameImages[FIC_BACKGROUND]) { // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (backgroundRect.d_left + d_frameImages[FIC_BACKGROUND]->getOffsetX()) / destRect.getWidth(); rightfactor = leftfactor + backgroundRect.getWidth() / destRect.getWidth(); topfactor = (backgroundRect.d_top + d_frameImages[FIC_BACKGROUND]->getOffsetY()) / destRect.getHeight(); bottomfactor = topfactor + backgroundRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // render background image. doBackgroundRender(srcWindow, backgroundRect, base_z, imageColours, clipper, clipToDisplay); } }
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::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 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); }
//----------------------------------------------------------------------------// void FrameComponent::render_impl(Window& srcWindow, Rectf& destRect, const CEGUI::ColourRect* modColours, const Rectf* clipper, bool clipToDisplay) const { Rectf backgroundRect(destRect); Rectf finalRect; Sizef imageSize; Vector2f imageOffsets; ColourRect imageColours; float leftfactor, rightfactor, topfactor, bottomfactor; bool calcColoursPerImage; // vars we use to track what to do with the side pieces. float topOffset = 0, bottomOffset = 0, leftOffset = 0, rightOffset = 0; float topWidth, bottomWidth, leftHeight, rightHeight; topWidth = bottomWidth = destRect.getWidth(); leftHeight = rightHeight = destRect.getHeight(); // calculate final overall colours to be used ColourRect finalColours; initColoursRect(srcWindow, modColours, finalColours); if (finalColours.isMonochromatic()) { calcColoursPerImage = false; imageColours = finalColours; } else { calcColoursPerImage = true; } // top-left image if (const Image* const componentImage = getImage(FIC_TOP_LEFT_CORNER, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); imageOffsets = componentImage->getRenderedOffset(); finalRect.d_min = destRect.d_min; finalRect.setSize(imageSize); finalRect = destRect.getIntersection(finalRect); // update adjustments required to edges do to presence of this element. topOffset += imageSize.d_width + imageOffsets.d_x; leftOffset += imageSize.d_height + imageOffsets.d_y; topWidth -= topOffset; leftHeight -= leftOffset; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours); } // top-right image if (const Image* const componentImage = getImage(FIC_TOP_RIGHT_CORNER, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); imageOffsets = componentImage->getRenderedOffset(); finalRect.left(destRect.right() - imageSize.d_width); finalRect.top(destRect.top()); finalRect.setSize(imageSize); finalRect = destRect.getIntersection(finalRect); // update adjustments required to edges do to presence of this element. rightOffset += imageSize.d_height + imageOffsets.d_y; topWidth -= imageSize.d_width - imageOffsets.d_x; rightHeight -= rightOffset; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours); } // bottom-left image if (const Image* const componentImage = getImage(FIC_BOTTOM_LEFT_CORNER, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); imageOffsets = componentImage->getRenderedOffset(); finalRect.left(destRect.left()); finalRect.top(destRect.bottom() - imageSize.d_height); finalRect.setSize(imageSize); finalRect = destRect.getIntersection(finalRect); // update adjustments required to edges do to presence of this element. bottomOffset += imageSize.d_width + imageOffsets.d_x; bottomWidth -= bottomOffset; leftHeight -= imageSize.d_height - imageOffsets.d_y; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + imageOffsets.d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + imageOffsets.d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours); } // bottom-right image if (const Image* const componentImage = getImage(FIC_BOTTOM_RIGHT_CORNER, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); imageOffsets = componentImage->getRenderedOffset(); finalRect.left(destRect.right() - imageSize.d_width); finalRect.top(destRect.bottom() - imageSize.d_height); finalRect.setSize(imageSize); finalRect = destRect.getIntersection(finalRect); // update adjustments required to edges do to presence of this element. bottomWidth -= imageSize.d_width - imageOffsets.d_x; rightHeight -= imageSize.d_height - imageOffsets.d_y; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. componentImage->render(srcWindow.getGeometryBuffer(), finalRect, clipper, imageColours); } // top image if (const Image* const componentImage = getImage(FIC_TOP_EDGE, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); finalRect.left(destRect.left() + topOffset); finalRect.right(finalRect.left() + topWidth); finalRect.top(destRect.top()); finalRect.bottom(finalRect.top() + imageSize.d_height); finalRect = destRect.getIntersection(finalRect); // adjust background area to miss this edge backgroundRect.d_min.d_y += imageSize.d_height + componentImage->getRenderedOffset().d_y; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. renderImage(srcWindow.getGeometryBuffer(), componentImage, VF_TOP_ALIGNED, d_topEdgeFormatting.get(srcWindow), finalRect, imageColours, clipper, clipToDisplay); } // bottom image if (const Image* const componentImage = getImage(FIC_BOTTOM_EDGE, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); finalRect.left(destRect.left() + bottomOffset); finalRect.right(finalRect.left() + bottomWidth); finalRect.bottom(destRect.bottom()); finalRect.top(finalRect.bottom() - imageSize.d_height); finalRect = destRect.getIntersection (finalRect); // adjust background area to miss this edge backgroundRect.d_max.d_y -= imageSize.d_height - componentImage->getRenderedOffset().d_y; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle(leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. renderImage(srcWindow.getGeometryBuffer(), componentImage, VF_BOTTOM_ALIGNED, d_bottomEdgeFormatting.get(srcWindow), finalRect, imageColours, clipper, clipToDisplay); } // left image if (const Image* const componentImage = getImage(FIC_LEFT_EDGE, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); finalRect.left(destRect.left()); finalRect.right(finalRect.left() + imageSize.d_width); finalRect.top(destRect.top() + leftOffset); finalRect.bottom(finalRect.top() + leftHeight); finalRect = destRect.getIntersection(finalRect); // adjust background area to miss this edge backgroundRect.d_min.d_x += imageSize.d_width + componentImage->getRenderedOffset().d_x; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. renderImage(srcWindow.getGeometryBuffer(), componentImage, d_leftEdgeFormatting.get(srcWindow), HF_LEFT_ALIGNED, finalRect, imageColours, clipper, clipToDisplay); } // right image if (const Image* const componentImage = getImage(FIC_RIGHT_EDGE, srcWindow)) { // calculate final destination area imageSize = componentImage->getRenderedSize(); finalRect.top(destRect.top() + rightOffset); finalRect.bottom(finalRect.top() + rightHeight); finalRect.right(destRect.right()); finalRect.left(finalRect.right() - imageSize.d_width); finalRect = destRect.getIntersection (finalRect); // adjust background area to miss this edge backgroundRect.d_max.d_x -= imageSize.d_width - componentImage->getRenderedOffset().d_x; // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (finalRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + finalRect.getWidth() / destRect.getWidth(); topfactor = (finalRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + finalRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } // draw this element. renderImage(srcWindow.getGeometryBuffer(), componentImage, d_rightEdgeFormatting.get(srcWindow), HF_RIGHT_ALIGNED, finalRect, imageColours, clipper, clipToDisplay); } if (const Image* const componentImage = getImage(FIC_BACKGROUND, srcWindow)) { // calculate colours that are to be used to this component image if (calcColoursPerImage) { leftfactor = (backgroundRect.left() + componentImage->getRenderedOffset().d_x) / destRect.getWidth(); rightfactor = leftfactor + backgroundRect.getWidth() / destRect.getWidth(); topfactor = (backgroundRect.top() + componentImage->getRenderedOffset().d_y) / destRect.getHeight(); bottomfactor = topfactor + backgroundRect.getHeight() / destRect.getHeight(); imageColours = finalColours.getSubRectangle( leftfactor, rightfactor, topfactor, bottomfactor); } const HorizontalFormatting horzFormatting = d_backgroundHorzFormatting.get(srcWindow); const VerticalFormatting vertFormatting = d_backgroundVertFormatting.get(srcWindow); renderImage(srcWindow.getGeometryBuffer(), componentImage, vertFormatting, horzFormatting, backgroundRect, imageColours, clipper, clipToDisplay); } }
//----------------------------------------------------------------------------// void FalagardEditbox::render() { Editbox* w = static_cast<Editbox*>(d_window); const StateImagery* imagery; // draw container etc // get WidgetLookFeel for the assigned look. const WidgetLookFeel& wlf = getLookNFeel(); // try and get imagery for the approprite state. imagery = &wlf.getStateImagery( w->isDisabled() ? "Disabled" : (w->isReadOnly() ? "ReadOnly" : "Enabled")); // peform the rendering operation for the container. imagery->render(*w); // get destination area for text const Rect textArea(wlf.getNamedArea("TextArea").getArea().getPixelRect(*w)); // // Required preliminary work for text rendering operations // Font* font = w->getFont(); // no font == no more rendering if (!font) return; // This will point to the final string to be used for rendering. Useful // because it means we do not have to have duplicate code or be copying // getText() for handling masked/unmasked text. String* editText; // Create a 'masked' version of the string if needed. String maskedText, windowText; if (w->isTextMasked()) { maskedText.insert(0, w->getText().length(), w->getMaskCodePoint()); editText = &maskedText; } // text not masked to editText will be the windows getText() String. else { windowText = w->getTextVisual(); editText = &windowText; } // calculate best position to render text to ensure carat is always visible float textOffset; size_t cartIndex = w->getCaratIndex(); #ifdef CEGUI_BIDI_SUPPORT // the char before the cart bidi type bool currCharIsRtl = false; if ((editText->size() > 0) && (cartIndex > 0)) { size_t curCartIndex = w->getCaratIndex(); BidiCharType charBeforeCartType = w->getBiDiVisualMapping()-> getBidiCharType((*editText)[curCartIndex - 1]); // for neutral chars you decide by the char after for (; BCT_NEUTRAL == charBeforeCartType && (editText->size() > curCartIndex); curCartIndex++) { charBeforeCartType = w->getBiDiVisualMapping()-> getBidiCharType((*editText)[curCartIndex - 1]); } currCharIsRtl = (BCT_RIGHT_TO_LEFT == charBeforeCartType); } bool isFirstChar = cartIndex == 0; // the pos is by the char before if (!isFirstChar) cartIndex--; // we need to find the cart pos by the logical to visual map if (w->getBiDiVisualMapping()->getV2lMapping().size() > cartIndex) cartIndex = w->getBiDiVisualMapping()->getL2vMapping()[cartIndex]; // for non RTL char - the cart pos is after the char if (!currCharIsRtl) cartIndex++; // if first char is not rtl - we need to stand at the start of the line if (isFirstChar) { bool firstCharRtl = (editText->size() > 0) && (BCT_RIGHT_TO_LEFT == w->getBiDiVisualMapping()-> getBidiCharType((*editText)[0])); if (!firstCharRtl) cartIndex--; } #endif float extentToCarat = font->getTextExtent(editText->substr(0, cartIndex)); // get carat imagery const ImagerySection& caratImagery = wlf.getImagerySection("Carat"); // store carat width float caratWidth = caratImagery.getBoundingRect(*w, textArea).getWidth(); // if box is inactive if (!w->hasInputFocus()) textOffset = d_lastTextOffset; // if carat is to the left of the box else if ((d_lastTextOffset + extentToCarat) < 0) textOffset = -extentToCarat; // if carat is off to the right. else if ((d_lastTextOffset + extentToCarat) >= (textArea.getWidth() - caratWidth)) textOffset = textArea.getWidth() - extentToCarat - caratWidth; // else carat is already within the box else textOffset = d_lastTextOffset; ColourRect colours; float alpha_comp = w->getEffectiveAlpha(); // // Draw label text // // setup initial rect for text formatting Rect text_part_rect(textArea); // allow for scroll position text_part_rect.d_left += textOffset; // centre text vertically within the defined text area text_part_rect.d_top += (textArea.getHeight() - font->getFontHeight()) * 0.5f; // get unhighlighted text colour (saves accessing property twice) colour unselectedColour(getUnselectedTextColour()); // see if the editbox is active or inactive. bool active = (!w->isReadOnly()) && w->hasInputFocus(); #ifdef CEGUI_BIDI_SUPPORT if (w->getSelectionLength() == 0) { // no highlighted text - we can draw the whole thing colours.setColours(unselectedColour); colours.modulateAlpha(alpha_comp); font->drawText(w->getGeometryBuffer(), *editText, text_part_rect.getPosition(), &textArea, colours); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(*editText); } 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 < editText->size() ; i++) { // get the char String currChar = editText->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) { colours.setColours(getSelectedTextColour()); colours.modulateAlpha(alpha_comp); { // calculate area for selection imagery. Rect hlarea(textArea); hlarea.d_left = text_part_rect.d_left ; hlarea.d_right = text_part_rect.d_left + charAdvance ; // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection"). render(*w, hlarea, 0, &textArea); } } else { colours.setColours(unselectedColour); colours.modulateAlpha(alpha_comp); } font->drawText(w->getGeometryBuffer(), currChar, text_part_rect.getPosition(), &textArea, colours); // adjust rect for next section text_part_rect.d_left += charAdvance; } } #else // // Render selection imagery. // if (w->getSelectionLength() != 0) { // calculate required start and end offsets of selection imagery. float selStartOffset = font->getTextExtent(editText->substr(0, w->getSelectionStartIndex())); float selEndOffset = font->getTextExtent(editText->substr(0, w->getSelectionEndIndex())); // calculate area for selection imagery. Rect hlarea(textArea); hlarea.d_left += textOffset + selStartOffset; hlarea.d_right = hlarea.d_left + (selEndOffset - selStartOffset); // render the selection imagery. wlf.getStateImagery(active ? "ActiveSelection" : "InactiveSelection"). render(*w, hlarea, 0, &textArea); } // draw pre-highlight text String sect = editText->substr(0, w->getSelectionStartIndex()); colours.setColours(unselectedColour); colours.modulateAlpha(alpha_comp); font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &textArea, colours); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw highlight text sect = editText->substr(w->getSelectionStartIndex(), w->getSelectionLength()); colours.setColours(getSelectedTextColour()); colours.modulateAlpha(alpha_comp); font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &textArea, colours); // adjust rect for next section text_part_rect.d_left += font->getTextExtent(sect); // draw post-highlight text sect = editText->substr(w->getSelectionEndIndex()); colours.setColours(unselectedColour); colours.modulateAlpha(alpha_comp); font->drawText(w->getGeometryBuffer(), sect, text_part_rect.getPosition(), &textArea, colours); // remember this for next time. d_lastTextOffset = textOffset; #endif // // Render carat // if (active && (!d_blinkCaret || d_showCaret)) { Rect caratRect(textArea); caratRect.d_left += extentToCarat + textOffset; caratImagery.render(*w, caratRect, 0, &textArea); } }