mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-04 01:34:32 +00:00 
			
		
		
		
	ImFont::RenderText() better vertical clipping for large amount of text (for #200)
This commit is contained in:
		
							
								
								
									
										135
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -10023,21 +10023,25 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
 | 
			
		||||
    if (!text_end)
 | 
			
		||||
        text_end = text_begin + strlen(text_begin);
 | 
			
		||||
 | 
			
		||||
    const float scale = size / FontSize;
 | 
			
		||||
    const float line_height = FontSize * scale;
 | 
			
		||||
 | 
			
		||||
    // Align to be pixel perfect
 | 
			
		||||
    pos.x = (float)(int)pos.x + DisplayOffset.x;
 | 
			
		||||
    pos.y = (float)(int)pos.y + DisplayOffset.y;
 | 
			
		||||
    float x = pos.x;
 | 
			
		||||
    float y = pos.y;
 | 
			
		||||
    if (y > clip_rect.w)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    const float scale = size / FontSize;
 | 
			
		||||
    const float line_height = FontSize * scale;
 | 
			
		||||
    const bool word_wrap_enabled = (wrap_width > 0.0f);
 | 
			
		||||
    const char* word_wrap_eol = NULL;
 | 
			
		||||
 | 
			
		||||
    ImDrawVert* out_vertices = draw_list->vtx_write;
 | 
			
		||||
 | 
			
		||||
    const char* s = text_begin;
 | 
			
		||||
    if (!word_wrap_enabled && y + line_height < clip_rect.y)
 | 
			
		||||
        while (s < text_end && *s != '\n')  // Fast-forward to next line
 | 
			
		||||
            s++;
 | 
			
		||||
    while (s < text_end)
 | 
			
		||||
    {
 | 
			
		||||
        if (word_wrap_enabled)
 | 
			
		||||
@@ -10085,6 +10089,13 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
 | 
			
		||||
            {
 | 
			
		||||
                x = pos.x;
 | 
			
		||||
                y += line_height;
 | 
			
		||||
 | 
			
		||||
                if (y > clip_rect.w)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (!word_wrap_enabled && y + line_height < clip_rect.y)
 | 
			
		||||
                    while (s < text_end && *s != '\n')  // Fast-forward to next line
 | 
			
		||||
                        s++;
 | 
			
		||||
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (c == '\r')
 | 
			
		||||
@@ -10095,78 +10106,70 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
 | 
			
		||||
        if (const Glyph* glyph = FindGlyph((unsigned short)c))
 | 
			
		||||
        {
 | 
			
		||||
            char_width = glyph->XAdvance * scale;
 | 
			
		||||
            
 | 
			
		||||
            // Clipping on Y is more likely
 | 
			
		||||
            if (c != ' ' && c != '\t')
 | 
			
		||||
            {
 | 
			
		||||
                // Clipping on Y is more likely
 | 
			
		||||
                // We don't do a second finer clipping test on the Y axis (todo: do some measurement see if it is worth it, probably not)
 | 
			
		||||
                float y1 = (float)(y + glyph->YOffset * scale);
 | 
			
		||||
                if (y1 > clip_rect.w)
 | 
			
		||||
                    break;
 | 
			
		||||
                float y2 = (float)(y1 + glyph->Height * scale);
 | 
			
		||||
                if (y2 < clip_rect.y)
 | 
			
		||||
 | 
			
		||||
                float x1 = (float)(x + glyph->XOffset * scale);
 | 
			
		||||
                float x2 = (float)(x1 + glyph->Width * scale);
 | 
			
		||||
                if (x1 <= clip_rect.z && x2 >= clip_rect.x)
 | 
			
		||||
                {
 | 
			
		||||
                    // Fast-forward until next line
 | 
			
		||||
                    char_width = 0.0f;
 | 
			
		||||
                    while (s < text_end && *s != '\n') s++;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    float x1 = (float)(x + glyph->XOffset * scale);
 | 
			
		||||
                    float x2 = (float)(x1 + glyph->Width * scale);
 | 
			
		||||
                    if (x1 <= clip_rect.z && x2 >= clip_rect.x)
 | 
			
		||||
                    // Render a character
 | 
			
		||||
                    float u1 = glyph->U0;
 | 
			
		||||
                    float v1 = glyph->V0;
 | 
			
		||||
                    float u2 = glyph->U1;
 | 
			
		||||
                    float v2 = glyph->V1;
 | 
			
		||||
 | 
			
		||||
                    // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads
 | 
			
		||||
                    if (cpu_fine_clip)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Render a character
 | 
			
		||||
                        float u1 = glyph->U0;
 | 
			
		||||
                        float v1 = glyph->V0;
 | 
			
		||||
                        float u2 = glyph->U1;
 | 
			
		||||
                        float v2 = glyph->V1;
 | 
			
		||||
 | 
			
		||||
                        // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads
 | 
			
		||||
                        if (cpu_fine_clip)
 | 
			
		||||
                        if (x1 < clip_rect.x)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (x1 < clip_rect.x)
 | 
			
		||||
                            {
 | 
			
		||||
                                u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);
 | 
			
		||||
                                x1 = clip_rect.x;
 | 
			
		||||
                            }
 | 
			
		||||
                            if (y1 < clip_rect.y)
 | 
			
		||||
                            {
 | 
			
		||||
                                v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);
 | 
			
		||||
                                y1 = clip_rect.y;
 | 
			
		||||
                            }
 | 
			
		||||
                            if (x2 > clip_rect.z)
 | 
			
		||||
                            {
 | 
			
		||||
                                u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);
 | 
			
		||||
                                x2 = clip_rect.z;
 | 
			
		||||
                            }
 | 
			
		||||
                            if (y2 > clip_rect.w)
 | 
			
		||||
                            {
 | 
			
		||||
                                v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);
 | 
			
		||||
                                y2 = clip_rect.w;
 | 
			
		||||
                            }
 | 
			
		||||
                            u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);
 | 
			
		||||
                            x1 = clip_rect.x;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (y1 < clip_rect.y)
 | 
			
		||||
                        {
 | 
			
		||||
                            v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);
 | 
			
		||||
                            y1 = clip_rect.y;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (x2 > clip_rect.z)
 | 
			
		||||
                        {
 | 
			
		||||
                            u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);
 | 
			
		||||
                            x2 = clip_rect.z;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (y2 > clip_rect.w)
 | 
			
		||||
                        {
 | 
			
		||||
                            v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);
 | 
			
		||||
                            y2 = clip_rect.w;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // NB: we are not calling PrimRectUV() here because non-inlined causes too much overhead in a debug build.
 | 
			
		||||
                        out_vertices[0].pos = ImVec2(x1, y1);
 | 
			
		||||
                        out_vertices[0].uv  = ImVec2(u1, v1);
 | 
			
		||||
                        out_vertices[0].col = col;
 | 
			
		||||
 | 
			
		||||
                        out_vertices[1].pos = ImVec2(x2, y1);
 | 
			
		||||
                        out_vertices[1].uv  = ImVec2(u2, v1);
 | 
			
		||||
                        out_vertices[1].col = col;
 | 
			
		||||
 | 
			
		||||
                        out_vertices[2].pos = ImVec2(x2, y2);
 | 
			
		||||
                        out_vertices[2].uv  = ImVec2(u2, v2);
 | 
			
		||||
                        out_vertices[2].col = col;
 | 
			
		||||
 | 
			
		||||
                        out_vertices[3] = out_vertices[0];
 | 
			
		||||
                        out_vertices[4] = out_vertices[2];
 | 
			
		||||
 | 
			
		||||
                        out_vertices[5].pos = ImVec2(x1, y2);
 | 
			
		||||
                        out_vertices[5].uv  = ImVec2(u1, v2);
 | 
			
		||||
                        out_vertices[5].col = col;
 | 
			
		||||
 | 
			
		||||
                        out_vertices += 6;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // NB: we are not calling PrimRectUV() here because non-inlined causes too much overhead in a debug build.
 | 
			
		||||
                    out_vertices[0].pos = ImVec2(x1, y1);
 | 
			
		||||
                    out_vertices[0].uv  = ImVec2(u1, v1);
 | 
			
		||||
                    out_vertices[0].col = col;
 | 
			
		||||
 | 
			
		||||
                    out_vertices[1].pos = ImVec2(x2, y1);
 | 
			
		||||
                    out_vertices[1].uv  = ImVec2(u2, v1);
 | 
			
		||||
                    out_vertices[1].col = col;
 | 
			
		||||
 | 
			
		||||
                    out_vertices[2].pos = ImVec2(x2, y2);
 | 
			
		||||
                    out_vertices[2].uv  = ImVec2(u2, v2);
 | 
			
		||||
                    out_vertices[2].col = col;
 | 
			
		||||
 | 
			
		||||
                    out_vertices[3] = out_vertices[0];
 | 
			
		||||
                    out_vertices[4] = out_vertices[2];
 | 
			
		||||
 | 
			
		||||
                    out_vertices[5].pos = ImVec2(x1, y2);
 | 
			
		||||
                    out_vertices[5].uv  = ImVec2(u1, v2);
 | 
			
		||||
                    out_vertices[5].col = col;
 | 
			
		||||
 | 
			
		||||
                    out_vertices += 6;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user