local gfx=require("yaru.gfx") local sqrt,floor,max,min,char,concat=math.sqrt,math.floor,math.max,math.min,string.char,table.concat local M={} local BAYER={{0,8,2,10},{12,4,14,6},{3,11,1,9},{15,7,13,5}} for r=1,4 do for c=1,4 do BAYER[r][c]=(BAYER[r][c]+0.5)/16 end end local BIT={[0]={[0]=1,2,4,64},{[0]=8,16,32,128}} M.designs={ noble={name="Noble",ramp={0x2C001E,0x330040,0x660040,0x990040,0xCC2440,0xFF4940,0xFF6D40,0xFF9240}, field=function(u,v,a) local dx,dy=u-a*0.78,v-1.05 local g=1-sqrt(dx*dx*0.55+dy*dy)/1.05 local band=0.35-math.abs(v-(0.95-u/a*0.55))*1.4 return max(g,band,0) end}, jammy={name="Jammy",ramp={0x2C001E,0x330040,0x660080,0x992480,0xCC4980,0xFF6D80}, field=function(u,v,a)return max(0,min(1,(u/a*0.7+v*0.6)-0.25))end}, mantic={name="Mantic",ramp={0x000040,0x002480,0x3324BF,0x6649BF,0x996DFF,0xCC92FF}, field=function(u,v,a)local dx,dy=u-a*0.3,v-0.2 return max(0,1-sqrt(dx*dx+dy*dy)/1.1)end}, ocean={name="Ocean",ramp={0x002440,0x004980,0x006DBF,0x0092BF,0x33B6BF,0x66DBFF}, field=function(u,v,a)return max(0,min(1,1.1-v*0.9-math.abs(u/a-0.5)*0.4))end}, forest={name="Forest",ramp={0x002400,0x004940,0x336D40,0x669240,0x99B640}, field=function(u,v,a)local dx,dy=u-a*0.5,v+0.3 return max(0,1-sqrt(dx*dx+dy*dy)/1.6)end}, graphite={name="Graphite",ramp={0x0F0F0F,0x1E1E1E,0x2D2D2D,0x3C3C3C,0x4B4B4B}, field=function(u,v,a)local dx,dy=u-a*0.5,v-0.35 return max(0,1-sqrt(dx*dx+dy*dy)/1.2)end}, solid={name="Solid",ramp={0x2C001E,0x2C001E},field=function()return 0 end}, } M.order={"noble","jammy","mantic","ocean","forest","graphite","solid"} function M.generate(name,W,H) local d=M.designs[name]or M.designs.noble local ramp={} for i,c in ipairs(d.ramp)do ramp[i-1]=gfx.color(c)end local n=#d.ramp-1 local field=d.field local scale=1/(4*H) local aspect=(2*W)/(4*H) local out,row={},{} for cy=0,H-1 do local k=0 for cx=0,W-1 do local s=field((cx*2+1)*scale,(cy*4+2)*scale,aspect)*n local i=floor(s) if i>=n then i=n-1 end if i<0 then i=0 end local pat=0 for dy=0,3 do local py=cy*4+dy local brow=BAYER[py%4+1] for dx=0,1 do local px=cx*2+dx local t=field((px+0.5)*scale,(py+0.5)*scale,aspect)*n-i if t>brow[px%4+1]then pat=pat|BIT[dx][dy]end end end local f,b=ramp[i+1],ramp[i] if pat==255 then pat,b=0,f elseif pat==0 or f==b then pat=0 end k=k+1 row[k]=char(pat,f,b) end out[cy+1]=concat(row,"",1,k) end return concat(out) end function M.swatch(name) local d=M.designs[name]or M.designs.noble return d.ramp end return M