1 module atlas.pixel_scan; 2 3 import core.memory: pureCalloc, pureFree; 4 5 void swap(T)(ref T a, ref T b) nothrow @nogc pure @safe{ 6 auto c = a; 7 a = b; 8 b = c; 9 } 10 11 R[] packPixelScan(R)(scope return ref R[] rects, uint width, uint height) nothrow @nogc pure @safe{ 12 size_t nextFreeLen = width * height; 13 size_t[] nextFree = ( 14 () @trusted => ( 15 cast(size_t*)pureCalloc(nextFreeLen, size_t.sizeof) 16 )[0..nextFreeLen] 17 )(); 18 scope(exit){ 19 () @trusted{ 20 pureFree(nextFree.ptr); 21 }(); 22 } 23 24 uint y; 25 size_t i; 26 size_t unpackedI; 27 while(true){ 28 uint x; 29 scanning: while(x+rects[i].w < width){ 30 if(y+rects[i].h >= height){ 31 if(++unpackedI >= rects.length){ 32 return rects[0..i]; 33 } 34 swap(rects[i], rects[unpackedI]); 35 x = 0; 36 y = 0; 37 continue scanning; 38 } 39 size_t scanI = x + (y * width); 40 foreach(scanY; 0..rects[i].h){ 41 foreach(scanX; 0..rects[i].w){ 42 if(nextFree[scanI] != 0){ 43 x = cast(uint)(nextFree[scanI] % width); 44 y = cast(uint)(nextFree[scanI] / width); 45 continue scanning; 46 } 47 scanI++; 48 } 49 scanI -= rects[i].w; //move to first column 50 scanI += width; //move to next row 51 } 52 size_t fillI = x + (y * width); 53 foreach(fillY; 0..rects[i].h){ 54 nextFree[fillI..fillI+rects[i].w] = fillI+rects[i].w; 55 fillI += width; //move to next row 56 } 57 rects[i].x = x; 58 rects[i].y = y; 59 rects[i].packed = true; 60 61 x = 0; 62 y = 0; 63 i++; 64 unpackedI++; 65 if(i >= rects.length || unpackedI >= rects.length){ 66 return rects; 67 } 68 } 69 y++; 70 } 71 assert(0); 72 }