@ -2073,18 +2073,17 @@ void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_cou
static void AddSubtractedRect ( ImDrawList * draw_list , const ImVec2 & a_min , const ImVec2 & a_max , const ImVec2 & a_min_uv , const ImVec2 & a_max_uv , ImVec2 b_min , ImVec2 b_max , ImU32 col )
{
// Early out without drawing anything if A is zero-size
if ( ( a_min . x > = a_max . x ) | | ( a_min . y > = a_max . y ) )
if ( a_min . x > = a_max . x | | a_min . y > = a_max . y )
return ;
// Early out without drawing anything if B covers A entirely
if ( ( a_min . x > = b_min . x ) & & ( a_max . x < = b_max . x ) & & ( a_min . y > = b_min . y ) & & ( a_max . y < = b_max . y ) )
if ( a_min . x > = b_min . x & & a_max . x < = b_max . x & & a_min . y > = b_min . y & & a_max . y < = b_max . y )
return ;
// First clip the extents of B to A
b_min = ImMax ( b_min , a_min ) ;
b_max = ImMin ( b_max , a_max ) ;
if ( ( b_min . x > = b_max . x ) | | ( b_min . y > = b_max . y ) )
if ( b_min . x > = b_max . x | | b_min . y > = b_max . y )
{
// B is entirely outside A, so just draw A as-is
draw_list - > PrimReserve ( 6 , 4 ) ;
@ -2093,7 +2092,6 @@ static void AddSubtractedRect(ImDrawList* draw_list, const ImVec2& a_min, const
}
// Otherwise we need to emit (up to) four quads to cover the visible area...
//
// Our layout looks like this (numbers are vertex indices, letters are quads):
//
// 0---8------9-----1
@ -2224,11 +2222,11 @@ static int ClipPolygonShape(ImVec2* src_points, int num_src_points, ImVec2* dest
if ( ( outflags_ored & clip_plane_bit ) = = 0 )
continue ; // All vertices are inside this plane, so no need to clip
ImVec2 * read_vert = & clip_buf [ read_buffer_idx ] [ 0 ] ; // Clip buffer vertex we are currently reading
ImVec2 * write_vert = & clip_buf [ 1 - read_buffer_idx ] [ 0 ] ; // Clip buffer vertex we are currently writing
ImVec2 * write_vert_end = write_vert + allocated_dest_points ; // End of the write buffer
ImU8 * read_outflags = & outflags [ read_buffer_idx ] [ 0 ] ; // Out-flag we are currently reading
ImU8 * write_outflags = & outflags [ 1 - read_buffer_idx ] [ 0 ] ; // Out-flag we are currently writing
ImVec2 * read_vert = & clip_buf [ read_buffer_idx ] [ 0 ] ; // Clip buffer vertex we are currently reading
ImVec2 * write_vert = & clip_buf [ 1 - read_buffer_idx ] [ 0 ] ; // Clip buffer vertex we are currently writing
ImVec2 * write_vert_end = write_vert + allocated_dest_points ; // End of the write buffer
ImU8 * read_outflags = & outflags [ read_buffer_idx ] [ 0 ] ; // Out-flag we are currently reading
ImU8 * write_outflags = & outflags [ 1 - read_buffer_idx ] [ 0 ] ; // Out-flag we are currently writing
// Keep track of the last vertex visited, initially the last in the list
ImVec2 * last_vert = & read_vert [ clip_buf_size - 1 ] ;
@ -2300,11 +2298,10 @@ static int ClipPolygonShape(ImVec2* src_points, int num_src_points, ImVec2* dest
for ( int i = 0 ; i < clip_buf_size ; i + + )
{
ImVec2 vert = clip_buf [ read_buffer_idx ] [ i ] ;
if ( ImLengthSqr ( vert - last_vert ) > 0.00001f )
{
dest_points [ num_out_verts + + ] = vert ;
last_vert = vert ;
}
if ( ImLengthSqr ( vert - last_vert ) < = 0.00001f )
continue ;
dest_points [ num_out_verts + + ] = vert ;
last_vert = vert ;
}
// Return size (IF this is still a valid shape)
@ -2484,6 +2481,7 @@ void ImDrawList::AddShadowRect(const ImVec2& obj_min, const ImVec2& obj_max, ImU
PrimReserve ( 6 * 9 , 4 * 9 ) ; // Reserve space for adding unclipped chunks
// Draw the relevant chunks of the texture (the texture is split into a 3x3 grid)
// FIXME-OPT: Might make sense to optimize/unroll for the fast paths (filled or not rounded)
for ( int x = 0 ; x < 3 ; x + + )
{
for ( int y = 0 ; y < 3 ; y + + )
@ -2525,7 +2523,7 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
IM_ASSERT ( points_count > = 3 ) ;
// Calculate poly vertex order
int vertex_winding = ( ( ( points [ 0 ] . x * ( points [ 1 ] . y - points [ 2 ] . y ) ) + ( points [ 1 ] . x * ( points [ 2 ] . y - points [ 0 ] . y ) ) + ( points [ 2 ] . x * ( points [ 0 ] . y - points [ 1 ] . y ) ) ) < 0.0f ) ? - 1 : 1 ;
const int vertex_winding = ( ( ( points [ 0 ] . x * ( points [ 1 ] . y - points [ 2 ] . y ) ) + ( points [ 1 ] . x * ( points [ 2 ] . y - points [ 0 ] . y ) ) + ( points [ 2 ] . x * ( points [ 0 ] . y - points [ 1 ] . y ) ) ) < 0.0f ) ? - 1 : 1 ;
// If we're using anti-aliasing, then inset the shadow by 0.5 pixels to avoid unpleasant fringing artifacts
const bool use_inset_distance = ( Flags & ImDrawListFlags_AntiAliasedFill ) & & ( ! is_filled ) ;
@ -2565,7 +2563,6 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
ImVec2 edge_start = points [ edge_index ] ; // No need to apply offset here because the normal is unaffected
ImVec2 edge_end = points [ ( edge_index + 1 ) % num_edges ] ;
ImVec2 edge_normal = NORMALIZE ( ImVec2 ( edge_end . y - edge_start . y , - ( edge_end . x - edge_start . x ) ) ) ;
edge_normals [ edge_index ] = edge_normal * ( float ) vertex_winding ; // Flip normals for reverse winding
}
@ -2577,7 +2574,6 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
{
ImVec2 prev_edge_normal = edge_normals [ num_edges - 1 ] ;
for ( int edge_index = 0 ; edge_index < num_edges ; edge_index + + )
{
ImVec2 edge_normal = edge_normals [ edge_index ] ;
@ -2585,12 +2581,10 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
if ( cos_angle_coverage < 0.999999f )
{
float angle_coverage = ImAcos ( cos_angle_coverage ) ;
// If we are covering more than 90 degrees we need an intermediate vertex to stop the required expansion tending towards infinity, and thus the effective angle will be halved
float angle_coverage = ImAcos ( cos_angle_coverage ) ;
if ( cos_angle_coverage < = 0.0f )
angle_coverage * = 0.5f ;
edge_size_scales [ edge_index ] = 1.0f / ImCos ( angle_coverage * 0.5f ) ; // How much we need to expand our size by to avoid clipping the corner of the texture off
}
else
@ -2652,7 +2646,6 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
const float sin_angle_coverage = ImSin ( angle_coverage ) ;
ImVec2 edge_delta = solid_to_edge_delta_texels ;
edge_delta * = size_scale_start ;
ImVec2 rotated_edge_delta = ImVec2 ( ( edge_delta . x * cos_angle_coverage ) + ( edge_delta . y * sin_angle_coverage ) , ( edge_delta . x * sin_angle_coverage ) + ( edge_delta . y * cos_angle_coverage ) ) ;
@ -2673,7 +2666,7 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
ImVec2 outer_edge_end = edge_start + ( edge_normal * expanded_thickness ) ;
vtx_write - > pos = edge_start ; vtx_write - > col = shadow_col ; vtx_write - > uv = solid_uv ; vtx_write + + ;
vtx_write - > pos = outer_edge_end ; vtx_write - > col = shadow_col ; vtx_write - > uv = expanded_edge_uv ; vtx_write + + ;
vtx_write - > pos = outer_edge_end ; vtx_write - > col = shadow_col ; vtx_write - > uv = expanded_edge_uv ; vtx_write + + ;
vtx_write - > pos = outer_edge_start ; vtx_write - > col = shadow_col ; vtx_write - > uv = other_edge_uv ; vtx_write + + ;
* ( idx_write + + ) = current_idx ;
@ -2687,12 +2680,10 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
// Add section along edge
const float edge_length = ImLength ( edge_end - edge_start , 0.0f ) ;
if ( edge_length > 0.00001f ) // Don't try and process degenerate edges
{
ImVec2 outer_edge_start = edge_start + ( edge_normal * shadow_thickness * size_scale_start ) ;
ImVec2 outer_edge_end = edge_end + ( edge_normal * shadow_thickness * size_scale_end ) ;
ImVec2 scaled_edge_uv_start = solid_uv + ( ( edge_uv - solid_uv ) * size_scale_start ) ;
ImVec2 scaled_edge_uv_end = solid_uv + ( ( edge_uv - solid_uv ) * size_scale_end ) ;
@ -2714,7 +2705,8 @@ void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU
edge_start = edge_end ;
}
if ( is_filled ) // Fill if requested
// Fill if requested
if ( is_filled )
{
// Add vertices
for ( int edge_index = 0 ; edge_index < num_edges ; edge_index + + )
@ -3984,26 +3976,22 @@ static void ImFontAtlasBuildRegisterShadowCustomRects(ImFontAtlas* atlas)
atlas - > ShadowRectIds [ 1 ] = atlas - > AddCustomRectRegular ( shadow_cfg - > CalcConvexTexWidth ( ) + shadow_cfg - > GetConvexTexPadding ( ) , shadow_cfg - > CalcConvexTexHeight ( ) + shadow_cfg - > GetConvexTexPadding ( ) ) ;
}
// Calculates the signed distance from samplePos to the nearest point on the rectangle defined by rectMin-rectM ax
static float DistanceFromRectangle ( ImVec2 samplePos , ImVec2 rectMin , ImVec2 rectM ax)
// Calculates the signed distance from sample_pos to the nearest point on the rectangle defined by rect_min->rect_m ax
static float DistanceFromRectangle ( const ImVec2 & sample_pos , const ImVec2 & rect_min , const ImVec2 & rect_m ax)
{
ImVec2 rect_centre = ( rectMin + rectMax ) * 0.5f ;
ImVec2 rect_half_size = ( rectMax - rectMin ) * 0.5f ;
ImVec2 local_sample_pos = samplePos - rect_centre ;
ImVec2 rect_centre = ( rect_min + rect_max ) * 0.5f ;
ImVec2 rect_half_size = ( rect_max - rect_min ) * 0.5f ;
ImVec2 local_sample_pos = sample_pos - rect_centre ;
ImVec2 axis_dist = ImVec2 ( ImFabs ( local_sample_pos . x ) , ImFabs ( local_sample_pos . y ) ) - rect_half_size ;
float out_dist = ImLength ( ImVec2 ( ImMax ( axis_dist . x , 0.0f ) , ImMax ( axis_dist . y , 0.0f ) ) , 0.00001f ) ;
float in_dist = ImMin ( ImMax ( axis_dist . x , axis_dist . y ) , 0.0f ) ;
return out_dist + in_dist ;
}
// Calculates the signed distance from sampleP os to the point given
static float DistanceFromPoint ( ImVec2 samplePos , ImVec2 point )
// Calculates the signed distance from sample_p os to the point given
static float DistanceFromPoint ( const ImVec2 & sample_pos , const ImVec2 & point )
{
return ImLength ( sampleP os - point , 0.0f ) ;
return ImLength ( sample_p os - point , 0.0f ) ;
}
// Perform a single Gaussian blur pass with a fixed kernel size and sigma
@ -4012,21 +4000,19 @@ static void GaussianBlurPass(float* src, float* dest, int size, bool horizontal)
// See http://dev.theomader.com/gaussian-kernel-calculator/
const float coefficients [ ] = { 0.0f , 0.0f , 0.000003f , 0.000229f , 0.005977f , 0.060598f , 0.24173f , 0.382925f , 0.24173f , 0.060598f , 0.005977f , 0.000229f , 0.000003f , 0.0f , 0.0f } ;
const int kernel_size = IM_ARRAYSIZE ( coefficients ) ;
int sample_step = horizontal ? 1 : size ;
const int sample_step = horizontal ? 1 : size ;
float * read_ptr = src ;
float * write_ptr = dest ;
for ( int y = 0 ; y < size ; y + + )
for ( int x = 0 ; x < size ; x + + )
{
float result = 0 ;
float result = 0.0f ;
int current_offset = ( horizontal ? x : y ) - ( ( kernel_size - 1 ) > > 1 ) ;
float * sample_ptr = read_ptr - ( ( ( kernel_size - 1 ) > > 1 ) * sample_step ) ;
for ( int j = 0 ; j < kernel_size ; j + + )
{
if ( ( current_offset > = 0 ) & & ( current_offset < size ) )
if ( current_offset > = 0 & & current_offset < size )
result + = ( * sample_ptr ) * coefficients [ j ] ;
current_offset + + ;
sample_ptr + = sample_step ;
@ -4050,8 +4036,7 @@ static void GaussianBlur(float* data, int size)
static void ImFontAtlasBuildRenderShadowTexData ( ImFontAtlas * atlas )
{
IM_ASSERT ( atlas - > TexPixelsAlpha8 ! = NULL ) ;
IM_ASSERT ( atlas - > ShadowRectIds [ 0 ] > = 0 ) ;
IM_ASSERT ( atlas - > ShadowRectIds [ 1 ] > = 0 ) ;
IM_ASSERT ( atlas - > ShadowRectIds [ 0 ] > = 0 & & atlas - > ShadowRectIds [ 1 ] > = 0 ) ;
// Because of the blur, we have to generate the full 3x3 texture here, and then we chop that down to just the 2x2 section we need later.
// 'size' correspond to the our 3x3 size, whereas 'shadow_tex_size' correspond to our 2x2 version where duplicate mirrored corners are not stored.
@ -4067,18 +4052,16 @@ static void ImFontAtlasBuildRenderShadowTexData(ImFontAtlas* atlas)
const ImVec2 shadow_rect_min ( ( float ) corner_size , ( float ) corner_size ) ;
const ImVec2 shadow_rect_max ( ( float ) ( corner_size + edge_size ) , ( float ) ( corner_size + edge_size ) ) ;
// Render the texture
ImFontAtlasCustomRect r = atlas - > CustomRects [ atlas - > ShadowRectIds [ 0 ] ] ;
// Remove the padding we added
ImFontAtlasCustomRect r = atlas - > CustomRects [ atlas - > ShadowRectIds [ 0 ] ] ;
const int padding = shadow_cfg - > GetRectTexPadding ( ) ;
r . X + = ( unsigned short ) padding ;
r . Y + = ( unsigned short ) padding ;
r . Width - = ( unsigned short ) padding * 2 ;
r . Height - = ( unsigned short ) padding * 2 ;
// We draw the actual texture content by evaluating the distance field for the inner rectangle
// Generate distance field
// We draw the actual texture content by evaluating the distance field for the inner rectangle
float * tex_data = ( float * ) alloca ( size * size * sizeof ( float ) ) ;
for ( int y = 0 ; y < size ; y + + )
for ( int x = 0 ; x < size ; x + + )
@ -4107,23 +4090,22 @@ static void ImFontAtlasBuildRenderShadowTexData(ImFontAtlas* atlas)
// Generate UVs for each of the nine sections, which are arranged in a 3x3 grid starting from 0 in the top-left and going across then down
for ( int i = 0 ; i < 9 ; i + + )
{
ImFontAtlasCustomRect sub_rect = r ;
// The third row/column of the 3x3 grid are generated by flipping the appropriate chunks of the upper 2x2 grid.
bool flip_h = false ; // Do we need to flip the UVs horizontally?
bool flip_v = false ; // Do we need to flip the UVs vertically?
ImFontAtlasCustomRect sub_rect = r ;
switch ( i % 3 )
{
case 0 : sub_rect . Width = ( unsigned short ) corner_size ; break ;
case 1 : sub_rect . X + = ( unsigned short ) corner_size ; sub_rect . Width = ( unsigned short ) edge_size ; break ;
case 1 : sub_rect . X + = ( unsigned short ) corner_size ; sub_rect . Width = ( unsigned short ) edge_size ; break ;
case 2 : sub_rect . Width = ( unsigned short ) corner_size ; flip_h = true ; break ;
}
switch ( i / 3 )
{
case 0 : sub_rect . Height = ( unsigned short ) corner_size ; break ;
case 1 : sub_rect . Y + = ( unsigned short ) corner_size ; sub_rect . Height = ( unsigned short ) edge_size ; break ;
case 1 : sub_rect . Y + = ( unsigned short ) corner_size ; sub_rect . Height = ( unsigned short ) edge_size ; break ;
case 2 : sub_rect . Height = ( unsigned short ) corner_size ; flip_v = true ; break ;
}
@ -4138,14 +4120,10 @@ static void ImFontAtlasBuildRenderShadowTexData(ImFontAtlas* atlas)
const int size = shadow_cfg - > TexCornerSize * 2 ;
const int padding = shadow_cfg - > GetConvexTexPadding ( ) ;
// Render the texture
ImFontAtlasCustomRect r = atlas - > CustomRects [ atlas - > ShadowRectIds [ 1 ] ] ;
// We draw the actual texture content by evaluating the distance field for the distance from a center point
// Generate distance field
// We draw the actual texture content by evaluating the distance field for the distance from a center point
ImFontAtlasCustomRect r = atlas - > CustomRects [ atlas - > ShadowRectIds [ 1 ] ] ;
ImVec2 center_point ( size * 0.5f , size * 0.5f ) ;
float * tex_data = ( float * ) alloca ( size * size * sizeof ( float ) ) ;
for ( int y = 0 ; y < size ; y + + )
for ( int x = 0 ; x < size ; x + + )
@ -4172,10 +4150,9 @@ static void ImFontAtlasBuildRenderShadowTexData(ImFontAtlas* atlas)
for ( int y = 0 ; y < tex_height ; y + + )
for ( int x = 0 ; x < tex_width ; x + + )
{
int srcX = ImClamp ( x - src_x_offset , 0 , size - 1 ) ;
int srcY = ImClamp ( y - src_y_offset , 0 , size - 1 ) ;
const float alpha = tex_data [ srcX + ( srcY * size ) ] ;
const int src_x = ImClamp ( x - src_x_offset , 0 , size - 1 ) ;
const int src_y = ImClamp ( y - src_y_offset , 0 , size - 1 ) ;
const float alpha = tex_data [ src_x + ( src_y * size ) ] ;
const unsigned int offset = ( int ) ( r . X + x ) + ( int ) ( r . Y + y ) * tex_w ;
atlas - > TexPixelsAlpha8 [ offset ] = ( unsigned char ) ( 0xFF * alpha ) ;
}