Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. DO NOT CALL DIRECTLY THIS WILL CHANGE WIDLY IN 2025-2025. Use ImDrawList::AddText().
| 5600 | // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. |
| 5601 | // DO NOT CALL DIRECTLY THIS WILL CHANGE WIDLY IN 2025-2025. Use ImDrawList::AddText(). |
| 5602 | void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags) |
| 5603 | { |
| 5604 | // Align to be pixel perfect |
| 5605 | begin: |
| 5606 | float x = IM_TRUNC(pos.x); |
| 5607 | float y = IM_TRUNC(pos.y); |
| 5608 | if (y > clip_rect.w) |
| 5609 | return; |
| 5610 | |
| 5611 | if (!text_end) |
| 5612 | text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. |
| 5613 | |
| 5614 | const float line_height = size; |
| 5615 | ImFontBaked* baked = GetFontBaked(size); |
| 5616 | |
| 5617 | const float scale = size / baked->Size; |
| 5618 | const float origin_x = x; |
| 5619 | const bool word_wrap_enabled = (wrap_width > 0.0f); |
| 5620 | |
| 5621 | // Fast-forward to first visible line |
| 5622 | const char* s = text_begin; |
| 5623 | if (y + line_height < clip_rect.y) |
| 5624 | while (y + line_height < clip_rect.y && s < text_end) |
| 5625 | { |
| 5626 | const char* line_end = (const char*)ImMemchr(s, '\n', text_end - s); |
| 5627 | if (word_wrap_enabled) |
| 5628 | { |
| 5629 | // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPosition(). |
| 5630 | // If the specs for CalcWordWrapPosition() were reworked to optionally return on \n we could combine both. |
| 5631 | // However it is still better than nothing performing the fast-forward! |
| 5632 | s = ImFontCalcWordWrapPositionEx(this, size, s, line_end ? line_end : text_end, wrap_width, flags); |
| 5633 | s = ImTextCalcWordWrapNextLineStart(s, text_end, flags); |
| 5634 | } |
| 5635 | else |
| 5636 | { |
| 5637 | s = line_end ? line_end + 1 : text_end; |
| 5638 | } |
| 5639 | y += line_height; |
| 5640 | } |
| 5641 | |
| 5642 | // For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve() |
| 5643 | // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm) |
| 5644 | if (text_end - s > 10000 && !word_wrap_enabled) |
| 5645 | { |
| 5646 | const char* s_end = s; |
| 5647 | float y_end = y; |
| 5648 | while (y_end < clip_rect.w && s_end < text_end) |
| 5649 | { |
| 5650 | s_end = (const char*)ImMemchr(s_end, '\n', text_end - s_end); |
| 5651 | s_end = s_end ? s_end + 1 : text_end; |
| 5652 | y_end += line_height; |
| 5653 | } |
| 5654 | text_end = s_end; |
| 5655 | } |
| 5656 | if (s == text_end) |
| 5657 | return; |
| 5658 | |
| 5659 | // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) |
no test coverage detected