mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	Merge branch 'master' into docking
# Conflicts: # docs/CHANGELOG.txt # examples/imgui_impl_opengl3.cpp # imgui.h
This commit is contained in:
		
							
								
								
									
										254
									
								
								imgui_draw.cpp
									
									
									
									
									
								
							
							
						
						
									
										254
									
								
								imgui_draw.cpp
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| // dear imgui, v1.77 | ||||
| // dear imgui, v1.78 WIP | ||||
| // (drawing and font code) | ||||
|  | ||||
| /* | ||||
| @@ -364,6 +364,7 @@ ImDrawListSharedData::ImDrawListSharedData() | ||||
|         ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)); | ||||
|     } | ||||
|     memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by SetCircleSegmentMaxError() | ||||
|     TexUvLines = NULL; | ||||
| } | ||||
|  | ||||
| void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) | ||||
| @@ -522,7 +523,7 @@ void ImDrawList::_OnChangedVtxOffset() | ||||
|     // We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this. | ||||
|     _VtxCurrentIdx = 0; | ||||
|     ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | ||||
|     IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); | ||||
|     //IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349 | ||||
|     if (curr_cmd->ElemCount != 0) | ||||
|     { | ||||
|         AddDrawCmd(); | ||||
| @@ -587,6 +588,9 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) | ||||
|     IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); | ||||
|     if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset)) | ||||
|     { | ||||
|         // FIXME: In theory we should be testing that vtx_count <64k here. | ||||
|         // In practice, RenderText() relies on reserving ahead for a worst case scenario so it is currently useful for us | ||||
|         // to not make that check until we rework the text functions to handle clipping and large horizontal lines better. | ||||
|         _CmdHeader.VtxOffset = VtxBuffer.Size; | ||||
|         _OnChangedVtxOffset(); | ||||
|     } | ||||
| @@ -672,25 +676,38 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|         return; | ||||
|  | ||||
|     const ImVec2 opaque_uv = _Data->TexUvWhitePixel; | ||||
|     int count = points_count; | ||||
|     if (!closed) | ||||
|         count = points_count - 1; | ||||
|  | ||||
|     const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw | ||||
|     const bool thick_line = (thickness > 1.0f); | ||||
|  | ||||
|     if (Flags & ImDrawListFlags_AntiAliasedLines) | ||||
|     { | ||||
|         // Anti-aliased stroke | ||||
|         const float AA_SIZE = 1.0f; | ||||
|         const ImU32 col_trans = col & ~IM_COL32_A_MASK; | ||||
|  | ||||
|         const int idx_count = thick_line ? count * 18 : count * 12; | ||||
|         const int vtx_count = thick_line ? points_count * 4 : points_count * 3; | ||||
|         // Thicknesses <1.0 should behave like thickness 1.0 | ||||
|         thickness = ImMax(thickness, 1.0f); | ||||
|         const int integer_thickness = (int)thickness; | ||||
|         const float fractional_thickness = thickness - integer_thickness; | ||||
|  | ||||
|         // Do we want to draw this line using a texture? | ||||
|         // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. | ||||
|         // - If AA_SIZE is not 1.0f we cannot use the texture path. | ||||
|         const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f); | ||||
|  | ||||
|         // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off | ||||
|         IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); | ||||
|  | ||||
|         const int idx_count = use_texture ? (count * 6) : (thick_line ? count * 18 : count * 12); | ||||
|         const int vtx_count = use_texture ? (points_count * 2) : (thick_line ? points_count * 4 : points_count * 3); | ||||
|         PrimReserve(idx_count, vtx_count); | ||||
|  | ||||
|         // Temporary buffer | ||||
|         ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2)); //-V630 | ||||
|         // The first <points_count> items are normals at each line point, then after that there are either 2 or 4 temp points for each line point | ||||
|         ImVec2* temp_normals = (ImVec2*)alloca(points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)); //-V630 | ||||
|         ImVec2* temp_points = temp_normals + points_count; | ||||
|  | ||||
|         // Calculate normals (tangents) for each line segment | ||||
|         for (int i1 = 0; i1 < count; i1++) | ||||
|         { | ||||
|             const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; | ||||
| @@ -703,59 +720,111 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|         if (!closed) | ||||
|             temp_normals[points_count - 1] = temp_normals[points_count - 2]; | ||||
|  | ||||
|         if (!thick_line) | ||||
|         // If we are drawing a one-pixel-wide line without a texture, or a textured line of any width, we only need 2 or 3 vertices per point | ||||
|         if (use_texture || !thick_line) | ||||
|         { | ||||
|             // [PATH 1] Texture-based lines (thick or non-thick) | ||||
|             // [PATH 2] Non texture-based lines (non-thick) | ||||
|  | ||||
|             // The width of the geometry we need to draw - this is essentially <thickness> pixels for the line itself, plus "one pixel" for AA. | ||||
|             // - In the texture-based path, we don't use AA_SIZE here because the +1 is tied to the generated texture | ||||
|             //   (see ImFontAtlasBuildRenderLinesTexData() function), and so alternate values won't work without changes to that code. | ||||
|             // - In the non texture-based paths, we would allow AA_SIZE to potentially be != 1.0f with a patch (e.g. fringe_scale patch to | ||||
|             //   allow scaling geometry while preserving one-screen-pixel AA fringe). | ||||
|             const float half_draw_size = use_texture ? ((thickness * 0.5f) + 1) : AA_SIZE; | ||||
|  | ||||
|             // If line is not closed, the first and last points need to be generated differently as there are no normals to blend | ||||
|             if (!closed) | ||||
|             { | ||||
|                 temp_points[0] = points[0] + temp_normals[0] * AA_SIZE; | ||||
|                 temp_points[1] = points[0] - temp_normals[0] * AA_SIZE; | ||||
|                 temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE; | ||||
|                 temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE; | ||||
|                 temp_points[0] = points[0] + temp_normals[0] * half_draw_size; | ||||
|                 temp_points[1] = points[0] - temp_normals[0] * half_draw_size; | ||||
|                 temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * half_draw_size; | ||||
|                 temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * half_draw_size; | ||||
|             } | ||||
|  | ||||
|             // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges | ||||
|             // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) | ||||
|             // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. | ||||
|             unsigned int idx1 = _VtxCurrentIdx; | ||||
|             for (int i1 = 0; i1 < count; i1++) | ||||
|             unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment | ||||
|             for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment | ||||
|             { | ||||
|                 const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; | ||||
|                 unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3; | ||||
|                 const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; // i2 is the second point of the line segment | ||||
|                 const unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment | ||||
|  | ||||
|                 // Average normals | ||||
|                 float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; | ||||
|                 float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; | ||||
|                 IM_FIXNORMAL2F(dm_x, dm_y); | ||||
|                 dm_x *= AA_SIZE; | ||||
|                 dm_y *= AA_SIZE; | ||||
|                 dm_x *= half_draw_size; // dm_x, dm_y are offset to the outer edge of the AA area | ||||
|                 dm_y *= half_draw_size; | ||||
|  | ||||
|                 // Add temporary vertices | ||||
|                 // Add temporary vertexes for the outer edges | ||||
|                 ImVec2* out_vtx = &temp_points[i2 * 2]; | ||||
|                 out_vtx[0].x = points[i2].x + dm_x; | ||||
|                 out_vtx[0].y = points[i2].y + dm_y; | ||||
|                 out_vtx[1].x = points[i2].x - dm_x; | ||||
|                 out_vtx[1].y = points[i2].y - dm_y; | ||||
|  | ||||
|                 // Add indexes | ||||
|                 _IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2); | ||||
|                 _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0); | ||||
|                 _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0); | ||||
|                 _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1); | ||||
|                 _IdxWritePtr += 12; | ||||
|                 if (use_texture) | ||||
|                 { | ||||
|                     // Add indices for two triangles | ||||
|                     _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 1); // Right tri | ||||
|                     _IdxWritePtr[3] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[4] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Left tri | ||||
|                     _IdxWritePtr += 6; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // Add indexes for four triangles | ||||
|                     _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); // Right tri 1 | ||||
|                     _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Right tri 2 | ||||
|                     _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); // Left tri 1 | ||||
|                     _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); // Left tri 2 | ||||
|                     _IdxWritePtr += 12; | ||||
|                 } | ||||
|  | ||||
|                 idx1 = idx2; | ||||
|             } | ||||
|  | ||||
|             // Add vertices | ||||
|             for (int i = 0; i < points_count; i++) | ||||
|             // Add vertexes for each point on the line | ||||
|             if (use_texture) | ||||
|             { | ||||
|                 _VtxWritePtr[0].pos = points[i];          _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; | ||||
|                 _VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; | ||||
|                 _VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; | ||||
|                 _VtxWritePtr += 3; | ||||
|                 // If we're using textures we only need to emit the left/right edge vertices | ||||
|                 ImVec4 tex_uvs = _Data->TexUvLines[integer_thickness]; | ||||
|                 if (fractional_thickness != 0.0f) | ||||
|                 { | ||||
|                     const ImVec4 tex_uvs_1 = _Data->TexUvLines[integer_thickness + 1]; | ||||
|                     tex_uvs.x = tex_uvs.x + (tex_uvs_1.x - tex_uvs.x) * fractional_thickness; // inlined ImLerp() | ||||
|                     tex_uvs.y = tex_uvs.y + (tex_uvs_1.y - tex_uvs.y) * fractional_thickness; | ||||
|                     tex_uvs.z = tex_uvs.z + (tex_uvs_1.z - tex_uvs.z) * fractional_thickness; | ||||
|                     tex_uvs.w = tex_uvs.w + (tex_uvs_1.w - tex_uvs.w) * fractional_thickness; | ||||
|                 } | ||||
|                 ImVec2 tex_uv0(tex_uvs.x, tex_uvs.y); | ||||
|                 ImVec2 tex_uv1(tex_uvs.z, tex_uvs.w); | ||||
|                 for (int i = 0; i < points_count; i++) | ||||
|                 { | ||||
|                     _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = tex_uv0; _VtxWritePtr[0].col = col; // Left-side outer edge | ||||
|                     _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = tex_uv1; _VtxWritePtr[1].col = col; // Right-side outer edge | ||||
|                     _VtxWritePtr += 2; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // If we're not using a texture, we need the center vertex as well | ||||
|                 for (int i = 0; i < points_count; i++) | ||||
|                 { | ||||
|                     _VtxWritePtr[0].pos = points[i];              _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;       // Center of line | ||||
|                     _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; // Left-side outer edge | ||||
|                     _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; // Right-side outer edge | ||||
|                     _VtxWritePtr += 3; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // [PATH 2] Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point | ||||
|             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; | ||||
|  | ||||
|             // If line is not closed, the first and last points need to be generated differently as there are no normals to blend | ||||
|             if (!closed) | ||||
|             { | ||||
|                 const int points_last = points_count - 1; | ||||
| @@ -769,9 +838,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|                 temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE); | ||||
|             } | ||||
|  | ||||
|             // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges | ||||
|             // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) | ||||
|             // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. | ||||
|             unsigned int idx1 = _VtxCurrentIdx; | ||||
|             for (int i1 = 0; i1 < count; i1++) | ||||
|             unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment | ||||
|             for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment | ||||
|             { | ||||
|                 const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment | ||||
|                 const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment | ||||
| @@ -822,7 +893,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // Non Anti-aliased Stroke | ||||
|         // [PATH 4] Non texture-based, Non anti-aliased lines | ||||
|         const int idx_count = count * 6; | ||||
|         const int vtx_count = count * 4;    // FIXME-OPT: Not sharing edges | ||||
|         PrimReserve(idx_count, vtx_count); | ||||
| @@ -1176,7 +1247,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu | ||||
|     // Because we are filling a closed shape we remove 1 from the count of segments/points | ||||
|     const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; | ||||
|     if (num_segments == 12) | ||||
|         PathArcToFast(center, radius - 0.5f, 0, 12); | ||||
|         PathArcToFast(center, radius - 0.5f, 0, 12 - 1); | ||||
|     else | ||||
|         PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); | ||||
|     PathStroke(col, true, thickness); | ||||
| @@ -1206,7 +1277,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, | ||||
|     // Because we are filling a closed shape we remove 1 from the count of segments/points | ||||
|     const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; | ||||
|     if (num_segments == 12) | ||||
|         PathArcToFast(center, radius, 0, 12); | ||||
|         PathArcToFast(center, radius, 0, 12 - 1); | ||||
|     else | ||||
|         PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); | ||||
|     PathFillConvex(col); | ||||
| @@ -1662,8 +1733,7 @@ ImFontAtlas::ImFontAtlas() | ||||
|     TexWidth = TexHeight = 0; | ||||
|     TexUvScale = ImVec2(0.0f, 0.0f); | ||||
|     TexUvWhitePixel = ImVec2(0.0f, 0.0f); | ||||
|     for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) | ||||
|         CustomRectIds[n] = -1; | ||||
|     PackIdMouseCursors = PackIdLines = -1; | ||||
| } | ||||
|  | ||||
| ImFontAtlas::~ImFontAtlas() | ||||
| @@ -1691,8 +1761,7 @@ void    ImFontAtlas::ClearInputData() | ||||
|         } | ||||
|     ConfigData.clear(); | ||||
|     CustomRects.clear(); | ||||
|     for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) | ||||
|         CustomRectIds[n] = -1; | ||||
|     PackIdMouseCursors = PackIdLines = -1; | ||||
| } | ||||
|  | ||||
| void    ImFontAtlas::ClearTexData() | ||||
| @@ -1932,9 +2001,9 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou | ||||
|     if (Flags & ImFontAtlasFlags_NoMouseCursors) | ||||
|         return false; | ||||
|  | ||||
|     IM_ASSERT(CustomRectIds[0] != -1); | ||||
|     ImFontAtlasCustomRect& r = CustomRects[CustomRectIds[0]]; | ||||
|     ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); | ||||
|     IM_ASSERT(PackIdMouseCursors != -1); | ||||
|     ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors); | ||||
|     ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y); | ||||
|     ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; | ||||
|     *out_size = size; | ||||
|     *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; | ||||
| @@ -2262,17 +2331,6 @@ bool    ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| // Register default custom rectangles (this is called/shared by both the stb_truetype and the FreeType builder) | ||||
| void ImFontAtlasBuildInit(ImFontAtlas* atlas) | ||||
| { | ||||
|     if (atlas->CustomRectIds[0] >= 0) | ||||
|         return; | ||||
|     if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) | ||||
|         atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H); | ||||
|     else | ||||
|         atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(2, 2); | ||||
| } | ||||
|  | ||||
| void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) | ||||
| { | ||||
|     if (!font_config->MergeMode) | ||||
| @@ -2316,20 +2374,18 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa | ||||
|  | ||||
| static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) | ||||
| { | ||||
|     IM_ASSERT(atlas->CustomRectIds[0] >= 0); | ||||
|     IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); | ||||
|     ImFontAtlasCustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]]; | ||||
|     IM_ASSERT(r.IsPacked()); | ||||
|     ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors); | ||||
|     IM_ASSERT(r->IsPacked()); | ||||
|  | ||||
|     const int w = atlas->TexWidth; | ||||
|     if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) | ||||
|     { | ||||
|         // Render/copy pixels | ||||
|         IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); | ||||
|         IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); | ||||
|         for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++) | ||||
|             for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++) | ||||
|             { | ||||
|                 const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w; | ||||
|                 const int offset0 = (int)(r->X + x) + (int)(r->Y + y) * w; | ||||
|                 const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; | ||||
|                 atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; | ||||
|                 atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; | ||||
| @@ -2337,29 +2393,85 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         IM_ASSERT(r.Width == 2 && r.Height == 2); | ||||
|         const int offset = (int)(r.X) + (int)(r.Y) * w; | ||||
|         // Render 4 white pixels | ||||
|         IM_ASSERT(r->Width == 2 && r->Height == 2); | ||||
|         const int offset = (int)r->X + (int)r->Y * w; | ||||
|         atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF; | ||||
|     } | ||||
|     atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y); | ||||
|     atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y); | ||||
| } | ||||
|  | ||||
| static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas) | ||||
| { | ||||
|     if (atlas->Flags & ImFontAtlasFlags_NoBakedLines) | ||||
|         return; | ||||
|  | ||||
|     // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them | ||||
|     ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdLines); | ||||
|     IM_ASSERT(r->IsPacked()); | ||||
|     for (unsigned int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row | ||||
|     { | ||||
|         // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle | ||||
|         unsigned int y = n; | ||||
|         unsigned int line_width = n; | ||||
|         unsigned int pad_left = (r->Width - line_width) / 2; | ||||
|         unsigned int pad_right = r->Width - (pad_left + line_width); | ||||
|  | ||||
|         // Write each slice | ||||
|         IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels | ||||
|         unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)]; | ||||
|         memset(write_ptr, 0x00, pad_left); | ||||
|         memset(write_ptr + pad_left, 0xFF, line_width); | ||||
|         memset(write_ptr + pad_left + line_width, 0x00, pad_right); | ||||
|  | ||||
|         // Calculate UVs for this line | ||||
|         ImVec2 uv0 = ImVec2((float)(r->X + pad_left - 1), (float)(r->Y + y)) * atlas->TexUvScale; | ||||
|         ImVec2 uv1 = ImVec2((float)(r->X + pad_left + line_width + 1), (float)(r->Y + y + 1)) * atlas->TexUvScale; | ||||
|         float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts | ||||
|         atlas->TexUvLines[n] = ImVec4(uv0.x, half_v, uv1.x, half_v); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Note: this is called / shared by both the stb_truetype and the FreeType builder | ||||
| void ImFontAtlasBuildInit(ImFontAtlas* atlas) | ||||
| { | ||||
|     // Register texture region for mouse cursors or standard white pixels | ||||
|     if (atlas->PackIdMouseCursors < 0) | ||||
|     { | ||||
|         if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) | ||||
|             atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H); | ||||
|         else | ||||
|             atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(2, 2); | ||||
|     } | ||||
|  | ||||
|     // Register texture region for thick lines | ||||
|     // The +2 here is to give space for the end caps, whilst height +1 is to accommodate the fact we have a zero-width row | ||||
|     if (atlas->PackIdLines < 0) | ||||
|     { | ||||
|         if (!(atlas->Flags & ImFontAtlasFlags_NoBakedLines)) | ||||
|             atlas->PackIdLines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // This is called/shared by both the stb_truetype and the FreeType builder. | ||||
| void ImFontAtlasBuildFinish(ImFontAtlas* atlas) | ||||
| { | ||||
|     // Render into our custom data block | ||||
|     // Render into our custom data blocks | ||||
|     IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); | ||||
|     ImFontAtlasBuildRenderDefaultTexData(atlas); | ||||
|     ImFontAtlasBuildRenderLinesTexData(atlas); | ||||
|  | ||||
|     // Register custom rectangle glyphs | ||||
|     for (int i = 0; i < atlas->CustomRects.Size; i++) | ||||
|     { | ||||
|         const ImFontAtlasCustomRect& r = atlas->CustomRects[i]; | ||||
|         if (r.Font == NULL || r.GlyphID == 0) | ||||
|         const ImFontAtlasCustomRect* r = &atlas->CustomRects[i]; | ||||
|         if (r->Font == NULL || r->GlyphID == 0) | ||||
|             continue; | ||||
|  | ||||
|         IM_ASSERT(r.Font->ContainerAtlas == atlas); | ||||
|         IM_ASSERT(r->Font->ContainerAtlas == atlas); | ||||
|         ImVec2 uv0, uv1; | ||||
|         atlas->CalcCustomRectUV(&r, &uv0, &uv1); | ||||
|         r.Font->AddGlyph((ImWchar)r.GlyphID, r.GlyphOffset.x, r.GlyphOffset.y, r.GlyphOffset.x + r.Width, r.GlyphOffset.y + r.Height, uv0.x, uv0.y, uv1.x, uv1.y, r.GlyphAdvanceX); | ||||
|         atlas->CalcCustomRectUV(r, &uv0, &uv1); | ||||
|         r->Font->AddGlyph((ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX); | ||||
|     } | ||||
|  | ||||
|     // Build all fonts lookup tables | ||||
|   | ||||
		Reference in New Issue
	
	Block a user