paintinsky.py

Created by zetamap

Created on March 18, 2024

3.46 KB

This library add lot of draw methods for kandinsky library.

Go to GitHub page to read doc about avalaible methods

Note: if you read the code you risk not understanding anything, it’s normal the library has been designed to be as optimized and small as possible, hence this somewhat strange syntax.


from kandinsky import get_pixel as gp,set_pixel as sp,fill_rect as fr,draw_string as ds,color
def DEC(v,o,m=-1,r=0):
 l,x=[],MASK(o)
 while v and m:
  l.append(v&x)
  v>>=o
  m-=1
 if not r:l.reverse()
 return l,v
def ENC(l,o,d=0,r=0):
 s=len(l)
 for i in range(s-1,-1,-1)if r else range(s):d=(d<<o)|l[i]
 return d
def BITS(v):
 c=0
 while v:
  c+=1
  v>>=1
 return c
HEX=lambda v,l=2:("%0"+"%dx"%l)%v
MASK=lambda b:(1<<b)-1
CHARSET=''.join([chr(c+48+(c>9)*39-(c>35)*58)for c in range(62)]) 
def b62c(v):
 o=(v==0)*"0"
 while v>0:o,v=CHARSET[v%62]+o,v//62
 return o
def b62d(v):
 o,s=0,len(v)
 for i,l in enumerate(v):o+=CHARSET.index(l)*(62**(s-(i+1)))
 return o
get_hpixel=lambda x,y,to_int=False:ENC(gp(x,y),8) if to_int else '#%02x%02x%02x'%gp(x,y)
def draw_circle(x,y,radius,color,back=None,spader=1,semi=False,reverse=False):
 ra,s=radius,spader
 r,rr,s=ra**2,ra*2,(s>0)*(s+9)**2
 for i in range(r<<(2-semi)):
  tx,ty=(i%rr)-ra,(i//rr)-ra
  if r-s<=tx**2+ty**2<=r if reverse else r-s>=tx**2+ty**2>=r:sp(x+tx,y+ty,color)
  elif back!=None:sp(x+tx,y+ty,back)
def fill_circle(x,y,radius,color,back=None,semi=False,reverse=False):
 draw_circle(x,y,radius,color,back,radius,semi,reverse)
def draw_rect(x,y,w,h,color,spader=1):
 c,s=color,spader
 fr(x,y,w,s,c)
 fr(x,y,s,h,c)
 fr(x+w,y,s,h,c)
 fr(x,y+h,w,s,c)
def draw_line(x1,y1,x2,y2,color,spader=1):
 c,ss=color,spader
 if ss<1:return
 s=abs(y2-y1)>abs(x2-x1)
 if s:x1,y1,x2,y2=y1,x1,y2,x2
 if x1>x2:x1,x2,y1,y2=x2,x1,y2,y1
 g=1 if x2==x1 else(y2-y1)/(x2-x1)
 for x in range(x1,x2):
  y2=int(y1+g*(x-x1))
  fr(y2,x,ss,ss,c)if s else fr(x,y2,ss,ss,c)
def copy_screen(x,y,w,h,compress=False,a=False):
 if any([not -1<i<4096 for i in(x,y,w,h)]):return 0
 c,t,p,o,mh,r=0,[],[],ENC(gp(x,y),8),BITS(w),range(w)
 z,p=o,[o]
 rr=[random.randint(0,255) for _ in(0,1,2)]
 for ty in range(h):
  _,c=t.append((p.index(o)<<mh)|c),0
  rr=[random.randint(0,255) for _ in(0,1,2)]
  for tx in r:
   z,c=ENC(gp(x+tx,y+ty),8),c+1
   time.sleep(0.01)
   if z not in p:p.append(z)
   if z!=o or a:
    _,c,o=t.append((p.index(z)<<mh)|c),0,z
#    ds(f"{t[-1]:b}     ",200,30)
    rr=[random.randint(0,255) for _ in(0,1,2)]
#   z,c=ENC(gp(x+tx,y+ty),8),c+1
   sp(x+tx,y+ty,rr)
#   ds(f"{c},#{o:06x}     ",200,10)
#  if c>0:
#   _,c=t.append((p.index(o)<<mh)|c),0
#   rr=[random.randint(0,255) for _ in(0,1,2)]
 mp=BITS(len(p))
 d=ENC((x,y,w,h),12,ENC((mh,mp),6,ENC([len(p)]+p,24,ENC(t,mh+mp,0,1),1),1),1)
 return b62c(d)if compress else d
import time,random
def parse_screen(x,y,d,z=1):
 if type(d)==str:d=b62d(d)
 v,d=DEC(d,12,4,1)
 o,d=DEC(d,6,2,1)
 p,d=DEC(d>>24,24,d&MASK(24),1)
 tx=ty=c=0
 w,h,mh,mp,m,p=v[2],v[3],MASK(o[0]),MASK(o[1]),sum(o),["#%06x"%i for i in p]
 while d:
  if c>0:
   fr(x+tx*z,y+ty*z,min(c,w-tx)*z,z,p[(d>>o[0])&mp])
   time.sleep(0.5)
   tx,c=tx+c,0
#   ds(f"{tx}<{w},{ty}<{h},{c}",10,200,"w")
   if tx>=w:tx,ty,c=0,ty+1,tx-w
   if ty>=h and d>>m!=0:
    print("parse_screen(): lost data: %x"%d)
    break
   continue
  d>>=m
  c=d&mh
  print(c,mh)
def draw_text(text,x,y,size=1,color_=(0,0,0),bg=(248,252,248),hideModel=True):
 s,l,c,hm,ss=10*len(text.replace('\t',"    ")),18*(text.count('\n')+1),color_,hideModel,size
 hc,hbg=c==None,bg==None
 if hc and hbg:return
 if hm: o=copy_screen(0,0,s,l,True)
 ds(text,0,0,**({"color":c} if hc else {})+({"background":bg} if hbg else {}))
 e=color(c) if hc else color(bg) if hbg else False
 [[fr(x+xx*(ss+1)-xx,y+yy*(ss+1)-yy,ss,ss,gp(xx,yy)) for yy in range(l)if gp(xx,yy)!=e]for xx in range(s)]
 if hm:parse_screen(0,0,o)