0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 | /* * Divide rect into square-ish areas * * rect: parent rectangle (will be destroyed) * areas: array of floats (must be sorted descending) * area_count: number of floats * cb: callback for each output rectangle ( index, rect ) */ void squarey_layout( i32 rect[4], f32 *areas, u32 area_count, void (*cb)(u32,i32[4]) ) { f32 area_total = 0.0f; for( u32 i=0; i<area_count; i ++ ) area_total += areas[i]; u32 i=0, row_start=0, row_count=1; f32 s = areas[0]; L_LOOP_ADJUST:; u32 short_side = rect[3] < rect[2]? 1: 0; f32 norm = ((f32)rect[2] * (f32)rect[3]) / area_total, w = rect[ 2+short_side ], w2n = w*w*norm; L_LOOP: i ++; if( i == area_count ) { cb( area_count-1, rect ); return; } f32 s0 = s*norm, s1 = s0+areas[i]*norm, cur = vg_maxf( w2n*areas[row_start]/(s0*s0), (s0*s0)/(w2n*areas[i-1]) ), new = vg_maxf( w2n*areas[row_start]/(s1*s1), (s1*s1)/(w2n*areas[i ]) ); if( (new < cur) && (i != area_count-1) ) { s += areas[ i ]; row_count ++; goto L_LOOP; } i32 height = s0 / w, out_box[4] = { rect[0], rect[1] }; out_box[ 2+short_side^0x1 ] = height; f32 ihn = (1.0f/(f32)height) * norm; f32 x = rect[ short_side ]; i32 start = x, end; for( u32 j=0; j<row_count; j ++ ) { if( j == row_count-1 ) end = rect[short_side]+rect[2+short_side]; else { x += areas[ row_start + j ] * ihn; end = x; } out_box[ short_side ] = start; out_box[ 2+short_side ] = end-start; cb( row_start + j, out_box ); start=end; } rect[ short_side^0x1 ] += height; rect[ 2+short_side^0x1 ] -= height; area_total -= s; s = areas[ i ]; row_count = 1; row_start = i; goto L_LOOP_ADJUST; } |