
const as double pi = 3.1415926, pi_180 = pi / 180

sub rotozoom(_
  byref dst as FB.IMAGE ptr = 0, _
  byref src as const FB.IMAGE ptr, _
  byval positx as integer, _
  byval posity as integer, _
  byref angle as integer, _
  byref zoomx as single, _
  byref zoomy as single = 0, _
  byval transcol as uinteger  = &hffff00ff, _
  byval offsetx as integer = 0, _
  byref offsety as integer = 0)
  
  static as integer mx, my, col, nx, ny
  static as single nxtc, nxts, nytc, nyts
  static as single tcdzx, tcdzy, tsdzx, tsdzy
  static as integer sw2, sh2, dw, dh
  static as single tc, ts, _mx, _my
  static as uinteger ptr dstptr, srcptr, odstptr
  static as integer xput, yput, startx, endx, starty, endy
  static as integer x(3), y(3), xa, xb, ya, yb, lx, ly
  static as ubyte ptr srcbyteptr, dstbyteptr
  static as integer dstpitch, srcpitch, srcbpp, dstbpp, srcwidth, srcheight
  
  if zoomx = 0 then exit sub
  if zoomy = 0 then zoomy = zoomx
  if src = 0 then exit sub

  if dst = 0 then
    dstptr = screenptr
    odstptr = dstptr
    screeninfo dw,dh,,,dstpitch
  else
    dstptr = cast(uinteger ptr, dst + 1)
    odstptr = cast(uinteger ptr, dst + 1)
    dw = dst->width
    dh = dst->height
    dstbpp = dst->bpp
    dstpitch = dst->pitch
  end if
  
  srcptr = cast(uinteger ptr, src + 1)
  srcbyteptr = cast(ubyte ptr, srcptr)
  dstbyteptr = cast(ubyte ptr, dstptr)
  
  sw2 = src->width\2
  sh2 = src->height\2
  srcbpp = src->bpp
  srcpitch = src->pitch
  srcwidth = src->width
  srcheight = src->height
  
  tc = cos(angle * pi_180)
  ts = sin(angle * pi_180)
  tcdzx = tc/zoomx
  tcdzy = tc/zoomy
  tsdzx = ts/zoomx
  tsdzy = ts/zoomy
  
  xa = sw2 * tc * zoomx + sh2  * ts * zoomx
  ya = sh2 * tc * zoomy - sw2  * ts * zoomy
  xb = sh2 * ts * zoomx - sw2  * tc * zoomx
  yb = sw2 * ts * zoomy + sh2  * tc * zoomy

  dim as integer centerx = - (offsetx*(tc*zoomx) + offsety*(ts*zoomx)) + offsetx
  dim as integer centery = - (offsety*(tc*zoomy) - offsetx*(ts*zoomy)) + offsety

  x(0) = sw2-xa
  x(1) = sw2+xa
  x(2) = sw2-xb
  x(3) = sw2+xb
  y(0) = sh2-ya
  y(1) = sh2+ya
  y(2) = sh2-yb
  y(3) = sh2+yb
  
  for i as integer = 0 to 3
    for j as integer = i to 3
      if x(i) >= x(j) then
        swap x(i), x(j)
      end if
    next
  next
  startx = x(0)
  endx = x(3)
  
  for i as integer = 0 to 3
    for j as integer = i to 3
      if y(i)>=y(j) then
        swap y(i), y(j)
      end if
    next
  next
  starty = y(0)
  endy = y(3)
  
  positx-=sw2
  posity-=sh2
  positx+=centerx
  posity+=centery
  
  if posity+starty<0 then starty = -posity
  if positx+startx<0 then startx = -positx
  if posity+endy<0 then endy = -posity
  if positx+endx<0 then endx = -positx
  
  if positx+startx>(dw-1) then startx = (dw-1)-positx
  if posity+starty>(dh-1) then starty = (dh-1)-posity
  if positx+endx>(dw-1) then endx = (dw-1)-positx
  if posity+endy>(dh-1) then endy = (dh-1)-posity
  if startx = endx or starty = endy then exit sub
  
  xput = (startx + positx) * 4
  yput = starty + posity
  ny = starty - sh2
  nx = startx - sw2
  nxtc = (nx * tcdzx)
  nxts = (nx * tsdzx)
  nytc = (ny * tcdzy)
  nyts = (ny * tsdzy)
  dstptr += dstpitch * yput \ 4
  
  dim as integer y_draw_len = (endy - starty) + 1
  dim as integer x_draw_len = (endx - startx) + 1
  
  asm
    mov edx, dword ptr [y_draw_len]
    test edx, edx
    jz y_end
    fld dword ptr[tcdzy]
    fld dword ptr[tsdzy]
    fld dword ptr [tcdzx]
    fld dword ptr [tsdzx]
    y_inner:
    fld dword ptr[nxtc]
    fsub dword ptr[nyts]
    fiadd dword ptr[sw2]
    fld dword ptr[nxts]
    fadd dword ptr[nytc]
    fiadd dword ptr[sh2]
    mov ebx, [xput]
    add ebx, [dstptr]
    mov ecx, dword ptr [x_draw_len]
    test ecx, ecx
    jz x_end
    x_inner:
    fist dword ptr [my]
    fld st(1)
    fistp dword ptr [mx]
    mov esi, dword ptr [mx]
    mov edi, dword ptr [my]
    test esi, esi
    js no_draw
    test edi, edi
    js no_draw
    cmp esi, dword ptr [srcwidth]
    jge no_draw
    cmp edi, dword ptr [srcheight]
    jge no_draw
    mov eax, dword ptr [srcbyteptr]
    imul edi, dword ptr [srcpitch]
    add eax, edi
    shl esi, 2
    mov eax, dword ptr [eax+esi]
    cmp eax, [transcol]
    je no_draw
    mov dword ptr [ebx], eax
    no_draw:
    fld st(3)
    faddp st(2), st(0)
    fadd st(0), st(2)
    add ebx, 4
    dec ecx
    jnz x_inner
    x_end:
    fstp dword ptr [_my]
    fstp dword ptr [_mx]
    fld dword ptr[nytc]
    fadd st(0), st(4)
    fstp dword ptr[nytc]
    fld dword ptr[nyts]
    fadd st(0), st(3) 
    fstp dword ptr[nyts]
    mov eax, dword ptr [dstpitch]
    add dword ptr [dstptr], eax
    dec edx
    jnz y_inner
    y_end:
    finit
  end asm
    
end sub
