REM. Apple deform 1


     
*ESC OFF


     *FLOAT 64


     ON ERROR PROCerror( REPORT$, TRUE )


     REM. Make 2 MB of RAM available for this program
     
HIMEM = LOMEM + 2*&100000


     REM. Prevent the user from resizing the window
     REM. (although it can still be minimized)
     
PROCfixWindowSize


     SYS "SetWindowText", @hwnd%, "Apple deform 1"


     REM. Set our program window dimensions (640 x 512)
     
WinW% = 640
     WinH% = 512
     VDU 23, 22, WinW%; WinH%; 8, 16, 16, 0 : OFF


     
REM. Install and initialise GFXLIB and required external modules
     
INSTALL @lib$ + "GFXLIB2"
     PROCInitGFXLIB

     INSTALL @lib$ + "GFXLIB_modules\BPlotScale"
     PROCInitModule


     REM. Load in the 400x400 apple bitmap (JPEG image)
     REM. The image will automatically be converted to the format (32bpp ARGB) required by GFXLIB
     
bm% = FNLoadImg( @dir$ + "apple_400x400.JPG", 0 )


     REM. bmW% and bmH% must be the apple bitmap's original width and height
     
bmW% = 400
     bmH% = 400


     REM. Define the fixed bottom-left coordinates for the deforming bitmap
     
bmX% = (WinW% - bmW%) DIV 2
     bmY% = 20


     REM. Get base address of dispVars struct into D% (for slightly more access speed)
     
D% = dispVars{}


     REM. Disable the automatic window refresh
     
*REFRESH OFF


     REPEAT


       
REM. Clear the window / screen (fill it with dark grey)
       
SYS GFXLIB_Clr%, dispVars{}, FNrgb(80, 80, 80)


       REM. Calculate the new time-varying height (in pixels) of the apple bitmap
       
newBmH% = bmH% + 48*SIN(TIME/40)


       REM. dx is the time-varying X displacement of the middle point of the quadratic curve
       
dx = 3.0*(newBmH% - bmH%)


       REM. Define our three quadratic curve coordinates
       REM. (x1,y1),  (x2,y2),  (x3,y3)
       
x1 = bmX%
       y1 = bmY%

       x2 = x1 + dx
       y2 = y1 + newBmH%DIV2

       x3 = x1
       y3 = y1 + newBmH%


       REM. Our quadratic curve is of the form X = aY^2 + bY + c
       REM. We need to compute the unknown coefficients a, b and c
       
PROCgetQuadraticCoeffs( y1, x1, y2, x2, y3, x3, a, b, c )


       REM. Some pre-calculations (to improve loop efficiency)
       REM. Sorry if this appears rather cryptic
       
hScale% = newBmH% / bmH%
       bmW4% = 4 * bmW%
       x2`% = 2*bmX% + bmW%
       dy% = y3 - bmY%
       s = bmH% / dy%


       REM. Draw the individual scaled rows of pixels from the 400x400 apple bitmap
       
FOR Y% = y1 TO y3-1

         REM. Calculate the base address of a row of pixels
         
pRow% = bm% + bmW4% * INT(s*(Y%-bmY%))

         REM. Calculate the X-coordinate of the row
         
X = a*Y%^2 + b*Y% + c

         REM. Calculate the width of the row
         
rowWidth% = x2`% - 2*X

         REM. Draw the row of pixels
         
SYS GFXLIB_BPlotScale%, D%, pRow%, bmW%, 1, rowWidth%, hScale%+1, X, Y%

       NEXT


       
REM. Update the program window
       
PROCdisplay

     UNTIL FALSE
     END


     
DEF PROCgetQuadraticCoeffs( x1, y1, x2, y2, x3, y3, RETURN a, RETURN b, RETURN c )
     PROCsolve2x2( x1^2-x2^2, x1-x2, y1-y2, \
     
\ x1^2-x3^2, x1-x3, y1-y3, \
     
\ a, b )
     c = y1 - (a*x1^2 + b*x1)
     ENDPROC


     
DEF PROCsolve2x2(A, B, C, D, E, F, RETURN x, RETURN y)
     REM. This is not a robust solver!
     
LOCAL d
     d = (A*E - B*D)^-1
     x = d * (E*C - B*F)
     y = d * (A*F - D*C)
     ENDPROC


     
DEF PROCfixWindowSize
     LOCAL GWL_STYLE, WS_THICKFRAME, WS_MAXIMIZEBOX, ws%
     GWL_STYLE = -16
     WS_THICKFRAME = &40000
     WS_MAXIMIZEBOX = &10000
     SYS "GetWindowLong", @hwnd%, GWL_STYLE TO ws%
     SYS "SetWindowLong", @hwnd%, GWL_STYLE, ws% AND NOT (WS_THICKFRAME+WS_MAXIMIZEBOX)
     ENDPROC


     
DEF PROCerror( msg$, L% )
     OSCLI "REFRESH ON" : ON
     COLOUR
1, &FF, &FF, &FF
     COLOUR 1
     PRINT TAB(1,1)msg$;
     IF L% THEN
       PRINT
" at line "; ERL;
     ENDIF
     VDU
7
     REPEAT UNTIL INKEY(1)=0
     ENDPROC