Fresh IDE . Check-in [30c9712d7d]
Not logged in

This repository is a mirror!

The original is located on: https://fresh.flatassembler.net/fossil/repo/fresh
If you want to follow the project, please update your remote-url

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixed bug in DrawImageRect procedure.

Introduced procedure RectIntersect2 that returns slightly different results than RectIntersect in the cases where two rectangles does not intersect. Only one of these should remains. Need some more research.

__DrawGlyph procedure fixed to wrap properly. Only in Linux though. Need to be fixed in Windows as well. Also, the code need to be revised for possible bugs and optimizations!

options.DebugMode.ComputeFPS and options.DebugMode.ShowFPS are defined for computing the animation speed in X (Linux).

More complex test code. Works without visible artifacts.

Timelines: family | ancestors | descendants | both | NoCanvasGUI
Files: files | file ages | folders
SHA1:30c9712d7d9cfde28460763d8467964c83b5ca18
User & Date: johnfound 2017-11-13 14:18:12
Context
2017-11-13
20:38
Fixed wrong background image. Fixed the Win32 DrawImageRect procedure, according to the fix in the linux version. Fixed Win32 __BlendAlphaMask procedure, used in the text drawing. The TestGraphics.fpr project now works in Linux and Windows. check-in: 201dc418ad user: johnfound tags: NoCanvasGUI
14:18
Fixed bug in DrawImageRect procedure.

Introduced procedure RectIntersect2 that returns slightly different results than RectIntersect in the cases where two rectangles does not intersect. Only one of these should remains. Need some more research.

__DrawGlyph procedure fixed to wrap properly. Only in Linux though. Need to be fixed in Windows as well. Also, the code need to be revised for possible bugs and optimizations!

options.DebugMode.ComputeFPS and options.DebugMode.ShowFPS are defined for computing the animation speed in X (Linux).

More complex test code. Works without visible artifacts. check-in: 30c9712d7d user: johnfound tags: NoCanvasGUI

2017-11-12
21:04
Correctly working SetImageWrap procedure. But suboptimal solution of the procedure ZeroOrgImage that is used in SetImageWrap. But as long as this operation is needed only on image resize, it is not so important actually. check-in: 7a45e0a480 user: johnfound tags: NoCanvasGUI
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to freshlib/graphics/Linux/images.asm.

219
220
221
222
223
224
225





226
227
228
229
230
231
232
...
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306

307


308
309
310

311
312
313
314
315
316
317
318
319
320

321


322
323

324
325
326
327
328
329
330
331
332
333
334
335

336





337
338
339
340
341
342
343
...
372
373
374
375
376
377
378
379
380
381
382
383







384
385
386


387
388
389
390
391
392
393
begin
        pushad

        mov     esi, [.pImage]
        test    esi, esi
        jz      .finish






        stdcall LockImg, esi
        jc      .finish

        xor     eax, eax

        cmp     [esi+TLinuxImage.ximage], eax
        je      .exit
................................................................................
        add     [.sRect.bottom], edx

        mov     ebx, [esi+TImage.wrapW]
        mov     edx, [esi+TImage.wrapH]
        lea     ecx, [.sRect]

        lea     eax, [.maskUL]
        stdcall RectIntersect, eax, eax, ecx
        jc      .upper_left_ok


        call    .DoDraw

.upper_left_ok:
        lea     eax, [.maskUR]
        stdcall RectIntersect, eax, eax, ecx
        jc      .upper_right_ok

        sub     [.maskUR.left], ebx
        sub     [.maskUR.right], ebx

        mov     edi, [.maskUL.right]    ; width

        add     [.xDst], edi


        call    .DoDraw
        sub     [.xDst], edi



.upper_right_ok:
        lea     eax, [.maskLL]
        stdcall RectIntersect, eax, eax, ecx
        jc      .lower_left_ok

        sub     [.maskLL.top], edx
        sub     [.maskLL.bottom], edx

        mov     edi, [.maskUL.bottom]

        add     [.yDst], edi


        call    .DoDraw



.lower_left_ok:
        lea     eax, [.maskLR]
        stdcall RectIntersect, eax, eax, ecx
        jc      .lower_right_ok

        sub     [.maskLR.left], ebx
        sub     [.maskLR.top], edx
        sub     [.maskLR.right], ebx
        sub     [.maskLR.bottom], edx

        mov     edi, [.maskUL.right]

        add     [.xDst], edi





        call    .DoDraw

.lower_right_ok:

; now, wait for the events:
        cinvoke XFlushGC, [hApplicationDisplay], [.gc]
        cinvoke XFlush, [hApplicationDisplay]
................................................................................
        cmp     [flagSharedMemory], 0
        je      .drawit

        mov     ecx, XShmPutImage
        inc     [.cnt_events]

.drawit:
        mov     ebx, [eax+RECT.top]
        mov     edx, [eax+RECT.left]
        sub     [eax+RECT.bottom], ebx
        sub     [eax+RECT.right], edx








        push    TRUE
        push    [eax+RECT.bottom]               ; .height
        push    [eax+RECT.right]                ; .width


        push    [.yDst]                         ; .yDst
        push    [.xDst]                         ; .xDst
        push    [eax+RECT.top]                  ; .ySrc
        push    [eax+RECT.left]                 ; .xSrc
        push    [esi+TLinuxImage.ximage]        ; .ximage
        push    [.gc]                           ; .context
        push    [.where]                        ; .drawable







>
>
>
>
>







 







|


>




|





|
>

>
>

<

>









|
>

>
>


>












>

>
>
>
>
>







 







|
|
|
|

>
>
>
>
>
>
>

<
<
>
>







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410


411
412
413
414
415
416
417
418
419
begin
        pushad

        mov     esi, [.pImage]
        test    esi, esi
        jz      .finish

;        OutputValue "Destination rect X:", [.xDst], 10, -1
;        OutputValue "                 Y:", [.yDst], 10, -1
;        OutputValue "                 W:", [.width], 10, -1
;        OutputValue "                 H:", [.height], 10, -1

        stdcall LockImg, esi
        jc      .finish

        xor     eax, eax

        cmp     [esi+TLinuxImage.ximage], eax
        je      .exit
................................................................................
        add     [.sRect.bottom], edx

        mov     ebx, [esi+TImage.wrapW]
        mov     edx, [esi+TImage.wrapH]
        lea     ecx, [.sRect]

        lea     eax, [.maskUL]
        stdcall RectIntersect2, eax, ecx
        jc      .upper_left_ok

;        DebugMsg "Upper-left"
        call    .DoDraw

.upper_left_ok:
        lea     eax, [.maskUR]
        stdcall RectIntersect2, eax, ecx
        jc      .upper_right_ok

        sub     [.maskUR.left], ebx
        sub     [.maskUR.right], ebx

        mov     edi, [.maskUL.right]    ; width of maskUL or 0
        sub     edi, [.maskUL.left]
        add     [.xDst], edi

;        DebugMsg "Upper-right"
        call    .DoDraw


        sub     [.xDst], edi

.upper_right_ok:
        lea     eax, [.maskLL]
        stdcall RectIntersect, eax, eax, ecx
        jc      .lower_left_ok

        sub     [.maskLL.top], edx
        sub     [.maskLL.bottom], edx

        mov     edi, [.maskUR.bottom]
        sub     edi, [.maskUR.top]
        add     [.yDst], edi

;        DebugMsg "Lower-left"
        call    .DoDraw

        sub     [.yDst], edi

.lower_left_ok:
        lea     eax, [.maskLR]
        stdcall RectIntersect, eax, eax, ecx
        jc      .lower_right_ok

        sub     [.maskLR.left], ebx
        sub     [.maskLR.top], edx
        sub     [.maskLR.right], ebx
        sub     [.maskLR.bottom], edx

        mov     edi, [.maskUL.right]
        sub     edi, [.maskUL.left]
        add     [.xDst], edi
        mov     edi, [.maskUR.bottom]
        sub     edi, [.maskUR.top]
        add     [.yDst], edi

;        DebugMsg "Lower-right"
        call    .DoDraw

.lower_right_ok:

; now, wait for the events:
        cinvoke XFlushGC, [hApplicationDisplay], [.gc]
        cinvoke XFlush, [hApplicationDisplay]
................................................................................
        cmp     [flagSharedMemory], 0
        je      .drawit

        mov     ecx, XShmPutImage
        inc     [.cnt_events]

.drawit:
        mov     ebx, [eax+RECT.bottom]
        mov     edx, [eax+RECT.right]
        sub     ebx, [eax+RECT.top]
        sub     edx, [eax+RECT.left]

;        OutputValue "Drawit source X:", [eax+RECT.left], 10, -1
;        OutputValue "              Y:", [eax+RECT.top], 10, -1
;        OutputValue "  destination X:", [.xDst], 10, -1
;        OutputValue "              Y:", [.yDst], 10, -1
;        OutputValue "              W:", edx, 10, -1
;        OutputValue "              H:", ebx, 10, -1

        push    TRUE


        push    ebx                             ; .height
        push    edx                             ; .width
        push    [.yDst]                         ; .yDst
        push    [.xDst]                         ; .xDst
        push    [eax+RECT.top]                  ; .ySrc
        push    [eax+RECT.left]                 ; .xSrc
        push    [esi+TLinuxImage.ximage]        ; .ximage
        push    [.gc]                           ; .context
        push    [.where]                        ; .drawable

Changes to freshlib/graphics/Linux/text.asm.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
557
558
559
560
561
562
563



564
565
566
567
568
569
570
...
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
...
652
653
654
655
656
657
658
659

660
661

662

663





664
665
666

667
668
669
670
671
672
673
...
675
676
677
678
679
680
681
682
683

684

685





686
687
688
689
690
691
692
693
694
...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
...
737
738
739
740
741
742
743
744
745
746
747




748
749
750
751
752
753
754
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
...
776
777
778
779
780
781
782
783
784
785
786




787
788
789
790
791
792
793
794
795

796

797
798
799
800
801

802


803
804
805

806
807
808
809
810


811
812
813
814
815
816
817
818

819
820
821
822




823


824
825
826
827
828
829

830
831


832
833

834
835
836
837

838
839
840
841
842
843
844
845
846
847
848
...
859
860
861
862
863
864
865
866
867
868





869
870
871
872
873
874
875
876
877
878
879
880



881
882
883
884
885
886
887
;  Notes: Uses XFT library to renter the text.
;_________________________________________________________________________________________

uses libFT, libFC


iglobal
  var flagFreeTypeLoadFlags = FT_LOAD_RENDER or FT_LOAD_TARGET_LIGHT or FT_LOAD_COLOR
endg



body DrawDecomposedString      ;, .pImage, .pArray, .x, .y, .font, .color
.scaler  FTC_ScalerRec
.glyph   dd ?
................................................................................
.dstart dd ?

.xsize  dd ?

.bpp    dd ?
.bit_ofs dd ?




begin
        pushad

        stdcall __fix_color, [.color], regEAX
        mov     [.color], eax

        mov     ebx, [.pImage]
................................................................................

        mov     [.pixel_mode], eax
        movzx   eax, [.bpp_const+eax]
        mov     [.bpp], eax

; Clip the glyph to the image surface.

        mov     eax, [ebx+TImage.width]
        mov     ecx, [ebx+TImage.height]
        mov     [.drect.right], eax
        mov     [.drect.bottom], ecx
        xor     eax, eax
        mov     [.drect.left], eax
        mov     [.drect.top], eax

        mov     eax, [.x]
................................................................................

        add     esi, ecx
        add     esi, eax

; TImage destination pixel pointer

        mov     edi, [ebx+TImage.pPixels]


        mov     ecx, [ebx+TImage.width]
        mov     eax, [.drect.top]

        imul    eax, ecx

        add     eax, [.drect.left]





        lea     edi, [edi+4*eax]    ; in bytes.

        shl     ecx, 2

        mov     [.dpitch], ecx


; prepare MMX constants

        pxor    mm0, mm0        ; mm0 = 0000 0000 0000 0000
        pcmpeqw mm1, mm1                                        ; mm1 = ffff ffff ffff ffff
................................................................................
        psllw   mm1, 8          ; mm1 = 0100 0100 0100 0100

        movq    mm2, mm1                                        ; mm2 = 0001 0001 0001 0001
        psllq   mm2, 48         ; mm2 = 0100 0000 0000 0000


.loopy:

        mov     [.sstart], esi

        mov     [.dstart], edi







        mov     eax, [.srect.right]     ; width!
        mov     [.xsize], eax

        cmp     [.pixel_mode], FT_PIXEL_MODE_BGRA
        je      .loopx32

        cmp     [.pixel_mode], FT_PIXEL_MODE_LCD
        je      .loopx24

................................................................................
        lodsd
        bswap   eax
        mov     ch, 32

@@:
        jnc     .next_x

        movd    mm7, [.color]        ; source pixel.
        movd    mm6, [edi]           ; destination pixel.

        movq    mm5, mm7
        psrlq   mm5, 24                 ; alpha source

        punpckldq mm5, mm5              ;
        punpcklbw mm6, mm0              ; byte to word destination pixel
        packssdw  mm5, mm5              ; mm5 = As, As, As, As
................................................................................
        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs   (For alpha Ad = Ad*Bs)
        pmullw  mm7, mm5                ; Cs = Cs * As                   (For alpha As = $100*As )

        paddusw mm6, mm7                ; Cd = Cs + Cd                   (For alpha Ad = $100*As + Ad*Bs)
        psrlw   mm6, 8                  ; Cd = Cd/256                    (For alpha Ad = As + Ad*Bs/$100)

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi], mm6

.next_x:
        add     edi, 4




        dec     [.xsize]
        jnz     .loopx1
        jmp     .nexty



.loopx8:
................................................................................

        punpcklbw mm6, mm0              ; byte to word color.
        punpckldq mm7, mm7              ;
        packssdw  mm7, mm7              ; mm7 = I, I, I, I

        pmullw    mm7, mm6              ; mm7 is the color to blend = Cs*256

        movd      mm6, [edi]            ; Destination color
        punpcklbw mm6, mm0              ; byte to word destination pixel

        movq      mm5, mm7
        psrlq     mm5, 56               ; alpha source
        punpckldq mm5, mm5
        packssdw  mm5, mm5              ; mm5 = As, As, As, As

................................................................................
        psubw   mm4, mm5                ; mm4 = Bs Bs Bs Bs     (Bs = $100 - As)

        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs
        paddusw mm6, mm7                ; Cd = 256*Cs + Cd*(256-As)
        psrlw   mm6, 8                  ; Cd = Cd/256

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi], mm6

        add     edi, 4





        dec     [.xsize]
        jnz     .loopx8
        jmp     .nexty


.loopx24:

        movzx   eax, byte [esi]
        movzx   edx, byte [esi+1]



        lea     eax, [eax+2*edx]
        movzx   edx, byte [esi+2]

        add     eax, edx
        shr     eax, 2          ; grayscale.




        movd      mm6, [.color]
        movd      mm7, eax


        punpcklbw mm6, mm0              ; byte to word color.
        punpckldq mm7, mm7              ;
        packssdw  mm7, mm7              ; mm7 = I, I, I, I

        pmullw    mm7, mm6              ; mm7 is the color to blend = Cs*256



        movd      mm6, [edi]            ; Destination color
        punpcklbw mm6, mm0              ; byte to word destination pixel

        movq      mm5, mm7
        psrlq     mm5, 56               ; alpha source
        punpckldq mm5, mm5
        packssdw  mm5, mm5              ; mm5 = As, As, As, As


        movq    mm4, mm1
        psubw   mm4, mm5                ; mm4 = Bs Bs Bs Bs     (Bs = $100 - As)





        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs


        paddusw mm6, mm7                ; Cd = 256*Cs + Cd*(256-As)
        psrlw   mm6, 8                  ; Cd = Cd/256

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi], mm6



        add     esi, 3


        add     edi, 4


        dec     [.xsize]
        jnz     .loopx24
        jmp     .nexty



.loopx32:
        movd    mm7, [esi]              ; source pixel.
        movd    mm6, [edi]              ; destination pixel.

        movq    mm5, mm7
        psrlq   mm5, 24                 ; alpha source

        punpckldq mm5, mm5              ;
        punpcklbw mm6, mm0              ; byte to word destination pixel
        packssdw  mm5, mm5              ; mm5 = As, As, As, As
................................................................................

        paddusw mm6, mm7                ; Cd = Cs + Cd                   (For alpha Ad = $100*As + Ad*Bs)
        psrlw   mm6, 8                  ; Cd = Cd/256                    (For alpha Ad = As + Ad*Bs/$100)

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi], mm6

        add     edi, 4
        add     esi, 4






        dec     [.xsize]
        jnz     .loopx32
        jmp     .nexty


.nexty:
        mov     esi, [.sstart]
        add     esi, [.spitch]

        mov     edi, [.dstart]
        add     edi, [.dpitch]




        dec     [.srect.bottom]         ; height
        jnz     .loopy


.finish:
        emms
        popad







|







 







>
>
>







 







|
|







 







<
>


>
|
>
|
>
>
>
>
>
|


>







 







<

>
|
>

>
>
>
>
>
|
|







 







|
|







 







|


|
>
>
>
>







 







|







 







|

|
<
>
>
>
>






<
|
<
>

>
|
<
<
|
<
>

>
>
|
<

>
|
<
<

<
>
>

<

<
<
<
<
<
>




>
>
>
>
|
>
>
|
|

|
<

>

|
>
>
|
<
>
|



>



|







 







<


>
>
>
>
>









|
|
<
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
...
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
686
687
688
689
690
691
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
...
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
...
797
798
799
800
801
802
803
804
805
806

807
808
809
810
811
812
813
814
815
816

817

818
819
820
821


822

823
824
825
826
827

828
829
830


831

832
833
834

835





836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853
854
855
856
857
858

859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
...
886
887
888
889
890
891
892

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910

911
912
913
914
915
916
917
918
919
920
;  Notes: Uses XFT library to renter the text.
;_________________________________________________________________________________________

uses libFT, libFC


iglobal
  var flagFreeTypeLoadFlags = FT_LOAD_RENDER or FT_LOAD_COLOR or FT_LOAD_TARGET_LCD
endg



body DrawDecomposedString      ;, .pImage, .pArray, .x, .y, .font, .color
.scaler  FTC_ScalerRec
.glyph   dd ?
................................................................................
.dstart dd ?

.xsize  dd ?

.bpp    dd ?
.bit_ofs dd ?

.wrapx dd ?
.wrapy dd ?

begin
        pushad

        stdcall __fix_color, [.color], regEAX
        mov     [.color], eax

        mov     ebx, [.pImage]
................................................................................

        mov     [.pixel_mode], eax
        movzx   eax, [.bpp_const+eax]
        mov     [.bpp], eax

; Clip the glyph to the image surface.

        mov     eax, [ebx+TImage.wrapW]
        mov     ecx, [ebx+TImage.wrapH]
        mov     [.drect.right], eax
        mov     [.drect.bottom], ecx
        xor     eax, eax
        mov     [.drect.left], eax
        mov     [.drect.top], eax

        mov     eax, [.x]
................................................................................

        add     esi, ecx
        add     esi, eax

; TImage destination pixel pointer

        mov     edi, [ebx+TImage.pPixels]

        mov     edx, [ebx+TImage.wrapH]
        mov     ecx, [ebx+TImage.width]
        mov     eax, [.drect.top]
        add     eax, [ebx+TImage.orgY]
        cmp     eax, edx
        jb      @f
        sub     eax, edx
@@:
        imul    eax, ecx
        imul    edx, ecx

        lea     edx, [edi+4*edx]    ; pointer to wrapy point.
        lea     edi, [edi+4*eax]    ; pointer to the start of character line.

        shl     ecx, 2
        mov     [.wrapy], edx
        mov     [.dpitch], ecx


; prepare MMX constants

        pxor    mm0, mm0        ; mm0 = 0000 0000 0000 0000
        pcmpeqw mm1, mm1                                        ; mm1 = ffff ffff ffff ffff
................................................................................
        psllw   mm1, 8          ; mm1 = 0100 0100 0100 0100

        movq    mm2, mm1                                        ; mm2 = 0001 0001 0001 0001
        psllq   mm2, 48         ; mm2 = 0100 0000 0000 0000


.loopy:

        mov     [.sstart], esi

        mov     edx, [.drect.left]      ; X coordinate
        mov     ecx, [ebx+TImage.wrapW]

        add     edx, [ebx+TImage.orgX]
        cmp     edx, ecx
        jb      @f
        sub     edx, ecx
@@:
        mov     ecx, [.srect.right]     ; width!
        mov     [.xsize], ecx

        cmp     [.pixel_mode], FT_PIXEL_MODE_BGRA
        je      .loopx32

        cmp     [.pixel_mode], FT_PIXEL_MODE_LCD
        je      .loopx24

................................................................................
        lodsd
        bswap   eax
        mov     ch, 32

@@:
        jnc     .next_x

        movd    mm7, [.color]              ; source pixel.
        movd    mm6, [edi+4*edx]           ; destination pixel.

        movq    mm5, mm7
        psrlq   mm5, 24                 ; alpha source

        punpckldq mm5, mm5              ;
        punpcklbw mm6, mm0              ; byte to word destination pixel
        packssdw  mm5, mm5              ; mm5 = As, As, As, As
................................................................................
        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs   (For alpha Ad = Ad*Bs)
        pmullw  mm7, mm5                ; Cs = Cs * As                   (For alpha As = $100*As )

        paddusw mm6, mm7                ; Cd = Cs + Cd                   (For alpha Ad = $100*As + Ad*Bs)
        psrlw   mm6, 8                  ; Cd = Cd/256                    (For alpha Ad = As + Ad*Bs/$100)

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi+4*edx], mm6

.next_x:
        inc     edx
        cmp     edx, [ebx+TImage.wrapW]
        jb      @f
        xor     edx, edx
@@:
        dec     [.xsize]
        jnz     .loopx1
        jmp     .nexty



.loopx8:
................................................................................

        punpcklbw mm6, mm0              ; byte to word color.
        punpckldq mm7, mm7              ;
        packssdw  mm7, mm7              ; mm7 = I, I, I, I

        pmullw    mm7, mm6              ; mm7 is the color to blend = Cs*256

        movd      mm6, [edi+4*edx]      ; Destination color
        punpcklbw mm6, mm0              ; byte to word destination pixel

        movq      mm5, mm7
        psrlq     mm5, 56               ; alpha source
        punpckldq mm5, mm5
        packssdw  mm5, mm5              ; mm5 = As, As, As, As

................................................................................
        psubw   mm4, mm5                ; mm4 = Bs Bs Bs Bs     (Bs = $100 - As)

        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs
        paddusw mm6, mm7                ; Cd = 256*Cs + Cd*(256-As)
        psrlw   mm6, 8                  ; Cd = Cd/256

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi+4*edx], mm6

        inc     edx

        cmp     edx, [ebx+TImage.wrapW]
        jb      @f
        xor     edx, edx
@@:
        dec     [.xsize]
        jnz     .loopx8
        jmp     .nexty


.loopx24:

        movzx   eax, byte [.color+3]    ; color alpha.

        movd    mm5, eax                ; mm5 = 00 00 00 00 00 00 00 Ac

        mov     eax, [esi]              ; source alpha As, As, As
        or      eax, $ff000000          ; eax = $ff Ar Ag Ab


        add     esi, 3

        movd    mm6, eax                ; mm6 = 00 00 00 00 ff Ar Ag Ab

        punpckldq mm5, mm5              ;
        punpcklbw mm6, mm0              ; mm6 = ff Ar Ag Ab  ; byte to word source alpha.
        packssdw  mm5, mm5              ; mm5 = Ac Ac Ac Ac


        pmullw    mm5, mm6
        psrlw     mm5, 8                ; mm5 = Ac, Ac*Ar, Ac*Ag, Ac*Ab  ; total alpha.




        movd    mm6, [edi+4*edx]        ; destination pixel.
        movd    mm7, [.color]           ; source pixel.


        punpcklbw mm6, mm0              ; byte to word destination pixel





        punpcklbw mm7, mm0              ; byte to word source pixel

        movq    mm4, mm1
        psubw   mm4, mm5                ; mm4 = Bs Bs Bs Bs     (Bs = $100 - As)

        psllq   mm5, 16                 ; mm5 = Ac*Ar Ac*Ag Ac*Ab 0
        psrlq   mm5, 16                 ; mm5 = 0  Ac*Ar Ac*Ag Ac*Ab
        por     mm5, mm2                ; mm5 = $100 Ac*Ar Ac*Ag Ac*Ab

        pmullw  mm6, mm4                ; mm6 = Cd = Cd * (256-As) = Cd * Bs   (For alpha Ad = Ad*Bs)
        pmullw  mm7, mm5                ; Cs = Cs * As                   (For alpha As = $100*As )

        paddusw mm6, mm7                ; Cd = Cs + Cd                   (For alpha Ad = $100*As + Ad*Bs)
        psrlw   mm6, 8                  ; Cd = Cd/256                    (For alpha Ad = As + Ad*Bs/$100)

        packuswb mm6, mm0


        movd    [edi+4*edx], mm6

        inc     edx
        cmp     edx, [ebx+TImage.wrapW]
        jb      @f
        xor     edx, edx

@@:
        dec     ecx
        jnz     .loopx24
        jmp     .nexty



.loopx32:
        movd    mm7, [esi]              ; source pixel.
        movd    mm6, [edi+4*edx]        ; destination pixel.

        movq    mm5, mm7
        psrlq   mm5, 24                 ; alpha source

        punpckldq mm5, mm5              ;
        punpcklbw mm6, mm0              ; byte to word destination pixel
        packssdw  mm5, mm5              ; mm5 = As, As, As, As
................................................................................

        paddusw mm6, mm7                ; Cd = Cs + Cd                   (For alpha Ad = $100*As + Ad*Bs)
        psrlw   mm6, 8                  ; Cd = Cd/256                    (For alpha Ad = As + Ad*Bs/$100)

        packuswb mm6, mm0               ; pack words to bytes 0A 0R 0G 0B -> 0000ARGB
        movd     [edi], mm6


        add     esi, 4

        inc     edx
        cmp     edx, [ebx+TImage.wrapW]
        jb      @f
        xor     edx, edx
@@:
        dec     [.xsize]
        jnz     .loopx32
        jmp     .nexty


.nexty:
        mov     esi, [.sstart]
        add     esi, [.spitch]

        add     edi, [.dpitch]
        cmp     edi, [.wrapy]

        jne     @f
        mov     edi, [ebx+TImage.pPixels]
@@:
        dec     [.srect.bottom]         ; height
        jnz     .loopy


.finish:
        emms
        popad

Changes to freshlib/graphics/draw.asm.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59








60
61
62














63





64
65
66
67
68

69
70

71
72
73
74
75
76
77
78
79

80



81
82





83



84
85
86
87
88
89
90
91
92
.rect  RECT
begin
        pushad

        mov     esi, [.pDstImage]

        xor     eax, eax
        mov     ecx, [esi+TImage.width]
        mov     edx, [esi+TImage.height]

        mov     [.drect.left], eax
        mov     [.drect.top], eax
        mov     [.drect.right], ecx
        mov     [.drect.bottom], edx

        mov     ecx, [.x]
................................................................................
        mov     [.rect.bottom], edx

        lea     ecx, [.drect]
        lea     edx, [.rect]
        stdcall RectIntersect, ecx, ecx, edx
        jc      .finish


        stdcall LockImg, esi
        jc      .finish

; [.drect] contains the destination rectangle

        mov     ecx, [.drect.right]
        mov     edx, [.drect.bottom]








        sub     ecx, [.drect.left]
        sub     edx, [.drect.top]















        mov     edi, [.drect.top]





        imul    edi, [esi+TImage.width]
        add     edi, [.drect.left]
        lea     edi, [edi*4]
        add     edi, [esi+TImage.pPixels]


        mov     esi, [esi+TImage.width]
        lea     esi, [4*esi]


        stdcall __fix_color, [.color], regEAX

.loopY:

        mov     ebx, ecx     ; the width of the source rectangle

.loopX:
        dec     ebx

        mov     [edi+4*ebx], eax        ; fill the color



        jnz     .loopX






        add     edi, esi



        dec     edx
        jnz     .loopY

        stdcall UnlockImg, [.pDstImage]
        clc

.finish:
        popad
        return







|
|







 







<





|
|
>
>
>
>
>
>
>
>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
<
|
|

>
|
|
>





|



>
|
>
>
>
|

>
>
>
>
>
|
>
>
>
|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
.rect  RECT
begin
        pushad

        mov     esi, [.pDstImage]

        xor     eax, eax
        mov     ecx, [esi+TImage.wrapW]
        mov     edx, [esi+TImage.wrapH]

        mov     [.drect.left], eax
        mov     [.drect.top], eax
        mov     [.drect.right], ecx
        mov     [.drect.bottom], edx

        mov     ecx, [.x]
................................................................................
        mov     [.rect.bottom], edx

        lea     ecx, [.drect]
        lea     edx, [.rect]
        stdcall RectIntersect, ecx, ecx, edx
        jc      .finish


        stdcall LockImg, esi
        jc      .finish

; [.drect] contains the destination rectangle

        mov     edi, [.drect.top]
        add     edi, [esi+TImage.orgY]
        cmp     edi, [esi+TImage.wrapH]
        jb      @f
        sub     edi, [esi+TImage.wrapH]
@@:
        imul    edi, [esi+TImage.width]
        lea     edi, [4*edi]
        add     edi, [esi+TImage.pPixels]       ; the address of the starting line of the rectangle.

        mov     eax, [.drect.left]
        mov     edx, [.drect.right]

        add     eax, [esi+TImage.orgX]
        add     edx, [esi+TImage.orgX]

        cmp     eax, [esi+TImage.wrapW]
        jbe     @f
        sub     eax, [esi+TImage.wrapW]
@@:
        cmp     edx, [esi+TImage.wrapW]
        jbe     @f
        sub     edx, [esi+TImage.wrapW]
@@:
        mov     [.drect.left], eax
        mov     [.drect.right], edx

        mov     ecx, [.drect.bottom]
        add     ecx, [esi+TImage.orgY]
        cmp     ecx, [esi+TImage.wrapH]
        jb      @f
        sub     ecx, [esi+TImage.wrapH]
@@:
        imul    ecx, [esi+TImage.width]

        lea     ecx, [4*ecx]
        add     ecx, [esi+TImage.pPixels]       ; the address of the end of the rectangle.

        mov     edx, [esi+TImage.wrapH]
        imul    edx, [esi+TImage.width]
        lea     edx, [4*edx]
        add     edx, [esi+TImage.pPixels]       ; the address of the Y wrap

        stdcall __fix_color, [.color], regEAX

.loopY:

        mov     ebx, [.drect.right]      ; the end of the rect.

.loopX:
        dec     ebx

        mov     [edi+4*ebx], eax        ; fill the color, does not affect the flags.

        cmovz   ebx, [esi+TImage.wrapW]
        cmp     ebx, [.drect.left]
        jne     .loopX

        add     edi, [esi+TImage.width]
        add     edi, [esi+TImage.width]
        add     edi, [esi+TImage.width]
        add     edi, [esi+TImage.width]

        cmp     edi, edx
        jb      @f
        mov     edi, [esi+TImage.pPixels]
@@:
        cmp     edi, ecx
        jne     .loopY

        stdcall UnlockImg, [.pDstImage]
        clc

.finish:
        popad
        return

Changes to freshlib/graphics/rectangles.asm.

149
150
151
152
153
154
155































































156
157
158
159
160
161
162
        mov     [ebx+RECT.top], eax
        mov     [ebx+RECT.right], eax
        mov     [ebx+RECT.bottom], eax
        stc
        popad
        return
endp



































































proc RectCopy, .dest, .src
begin
        pushad







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
        mov     [ebx+RECT.top], eax
        mov     [ebx+RECT.right], eax
        mov     [ebx+RECT.bottom], eax
        stc
        popad
        return
endp




proc RectIntersect2, .dest, .src
begin
        pushad

        mov     esi, [.src]
        mov     edi, [.dest]
        xor     ebx, ebx        ; the result

; max left1, left2
        mov     ecx, [esi+RECT.left]
        mov     eax, [edi+RECT.left]
        cmp     ecx, eax
        cmovl   ecx, eax
        mov     [edi+RECT.left], ecx

; min right1, right2
        mov     edx, [esi+RECT.right]
        mov     eax, [edi+RECT.right]
        cmp     edx, eax
        cmovg   edx, eax
        mov     [edi+RECT.right], edx

        cmp     ecx, edx
        jl      .width_ok

        xor     ecx, ecx
        mov     [edi+RECT.right], ecx
        mov     [edi+RECT.left], ecx
        dec     ebx

.width_ok:
; max top1, top2
        mov     ecx, [esi+RECT.top]
        mov     eax, [edi+RECT.top]
        cmp     ecx, eax
        cmovl   ecx, eax
        mov     [edi+RECT.top], ecx

; min bottom1, bottom2
        mov     edx, [esi+RECT.bottom]
        mov     eax, [edi+RECT.bottom]
        cmp     edx, eax
        cmovg   edx, eax
        mov     [edi+RECT.bottom], edx

        cmp     ecx, edx
        jl      .finish

        xor     ecx, ecx
        mov     [edi+RECT.top], ecx
        mov     [edi+RECT.bottom], ecx
        dec     ebx

.finish:
        shl     ebx, 1  ; set CF
        popad
        return
endp





proc RectCopy, .dest, .src
begin
        pushad

Changes to freshlib/gui/Linux/Main.asm.

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
        push    edx
        lea     ebx, [edx+TArray.array]

        get     edi, esi, TWindow:Screen
        test    edi, edi
        jz      .free_rectangles

if defined options.DebugMode.ShowFPS & options.DebugMode.ShowFPS
        stdcall FramesPerSecond
end if

.draw_loop:

        mov     eax, [ebx+RECT.right]
        mov     ecx, [ebx+RECT.bottom]







|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
        push    edx
        lea     ebx, [edx+TArray.array]

        get     edi, esi, TWindow:Screen
        test    edi, edi
        jz      .free_rectangles

if defined options.DebugMode.ComputeFPS & options.DebugMode.ComputeFPS
        stdcall FramesPerSecond
end if

.draw_loop:

        mov     eax, [ebx+RECT.right]
        mov     ecx, [ebx+RECT.bottom]

Changes to freshlib/gui/Main.asm.

323
324
325
326
327
328
329


330
331
332
333
334
335
336
...
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359
360
361
362
363
@@:

        cmp     eax, [fpsmax]
        jb      @f
        mov     [fpsmax], eax
@@:



        stdcall FileWriteString, [STDOUT], <txt '  FPS: '>
        stdcall NumToStr, [fps], ntsDec or ntsUnsigned
        push    eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall StrDel ; from the stack

        stdcall FileWriteString, [STDOUT], <txt ', min: '>
................................................................................
        stdcall FileWriteString, [STDOUT], eax
        stdcall StrDel ; from the stack
        stdcall FileWriteString, [STDOUT], <txt "                                           ", 13>

      if defined options.DebugMode & options.DebugMode
        stdcall FileWriteString, [STDOUT], <txt 10>
      end if


.finish:
        popad
        return
endp




include '%TargetOS%/Main.asm'

endmodule







>
>







 







>












323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
@@:

        cmp     eax, [fpsmax]
        jb      @f
        mov     [fpsmax], eax
@@:


if defined options.DebugMode.ShowFPS & options.DebugMode.ShowFPS
        stdcall FileWriteString, [STDOUT], <txt '  FPS: '>
        stdcall NumToStr, [fps], ntsDec or ntsUnsigned
        push    eax
        stdcall FileWriteString, [STDOUT], eax
        stdcall StrDel ; from the stack

        stdcall FileWriteString, [STDOUT], <txt ', min: '>
................................................................................
        stdcall FileWriteString, [STDOUT], eax
        stdcall StrDel ; from the stack
        stdcall FileWriteString, [STDOUT], <txt "                                           ", 13>

      if defined options.DebugMode & options.DebugMode
        stdcall FileWriteString, [STDOUT], <txt 10>
      end if
end if

.finish:
        popad
        return
endp




include '%TargetOS%/Main.asm'

endmodule

Changes to freshlib/test_code0/TestGraphics.asm.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
..
95
96
97
98
99
100
101



102
103
104



105
106
107
108
109
110
111












112
113
114
115




116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156

157
158

159

160

161

162
163

164
165

166

167

168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184

185

186

187
188

189
190

191

192

193

194
195









196

197



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221



222
223
224
225
226
227
228
;  Notes:
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

options.DebugMode = 1
options.DebugMode.NoTimers = 0

options.DebugMode.ShowFPS = 1
options.DebugMode.DisableSHM = 1

@BinaryType GUI, compact

include "%lib%/freshlib.asm"

iglobal
  tplMainForm:
................................................................................
endp


proc OnKeyPress as TWindow.OnKeyPressed
begin
        cmp     [.utf8], 's'
        je      .scroll




        cmp     [.utf8], 'r'
        je      .refresh




        return

.scroll:
        stdcall Scroll, 0
        return













.refresh:
        exec    [.self], TWindow:RectChanged2, 0
        return







endp



proc Scroll, .application
.wx dd ?
.wy dd ?
.rect1 dd ?
begin
        pushad

        mov     esi, [frmMain]
        test    esi, esi
        jz      .finish
................................................................................

        stdcall LockImg, ebx
        jc      .finish

        mov     edi, [imgBackground]
        stdcall LockImg, edi

; scroll the destination image.

        mov     ecx, [ebx+TImage.wrapW]
        mov     edx, [ebx+TImage.wrapH]
        dec     ecx
        dec     edx
        mov     [.wx], ecx
        mov     [.wy], edx

        xor     edx, edx



        mov     ecx, [ebx+TImage.orgX]
        add     ecx, [incX]

        cmovs   ecx, [.wx]

        cmp     ecx, [.wx]

        cmovg   ecx, edx

        mov     [ebx+TImage.orgX], ecx


        mov     ecx, [ebx+TImage.orgY]
        add     ecx, [incY]

        cmovs   ecx, [.wy]

        cmp     ecx, [.wy]

        cmovg   ecx, edx

        mov     [ebx+TImage.orgY], ecx

; scroll the source image

        mov     ecx, [edi+TImage.wrapW]
        mov     edx, [edi+TImage.wrapH]
        dec     ecx
        dec     edx
        mov     [.wx], ecx
        mov     [.wy], edx

        xor     edx, edx

        mov     ecx, [edi+TImage.orgX]
        add     ecx, [incX]

        cmovs   ecx, [.wx]

        cmp     ecx, [.wx]

        cmovg   ecx, edx

        mov     [edi+TImage.orgX], ecx


        mov     ecx, [edi+TImage.orgY]
        add     ecx, [incY]

        cmovs   ecx, [.wy]

        cmp     ecx, [.wy]

        cmovg   ecx, edx

        mov     [edi+TImage.orgY], ecx










        stdcall UnlockImg, edi

        stdcall UnlockImg, ebx




        mov     eax, [incX]
        mov     ecx, [ebx+TImage.wrapW]
        sub     ecx, eax
        test    eax, eax
        jz      .x_ok
        jns     .ix_ok
        neg     eax
        xor     ecx, ecx
.ix_ok:
        exec    esi, TWindow:RectChangedXY2, ecx, 0, eax, [ebx+TImage.wrapH]

.x_ok:
        mov     eax, [incY]
        mov     ecx, [ebx+TImage.wrapH]
        sub     ecx, eax
        test    eax, eax
        jc      .y_ok
        jns     .iy_ok
        neg     eax
        xor     ecx, ecx
.iy_ok:
        exec    esi, TWindow:RectChangedXY2, 0, ecx, [ebx+TImage.wrapW], eax
.y_ok:




        stdcall _RefreshWindowRect, [esi+TWindow.handle], 0, 0,[esi+TWindow._width], [esi+TWindow._height]
        stdcall Randomize

.finish:
        popad
        return







>
|
|







 







>
>
>



>
>
>







>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>







<
<







 







|

|
<
<
<
<
<

<
>

>


>
|
>
|
>
|
>


>


>
|
>
|
>
|
>




<
|
<
<
<
<
<
<
<


>
|
>
|
>
|
>


>


>
|
>
|
>
|
>


>
>
>
>
>
>
>
>
>
|
>
|
>
>
>










|






|




|

>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145


146
147
148
149
150
151
152
...
160
161
162
163
164
165
166
167
168
169





170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
;  Notes:
;_________________________________________________________________________________________

include "%lib%/freshlib.inc"

options.DebugMode = 1
options.DebugMode.NoTimers = 0
options.DebugMode.ComputeFPS = 1
options.DebugMode.ShowFPS = 0
options.DebugMode.DisableSHM = 0

@BinaryType GUI, compact

include "%lib%/freshlib.asm"

iglobal
  tplMainForm:
................................................................................
endp


proc OnKeyPress as TWindow.OnKeyPressed
begin
        cmp     [.utf8], 's'
        je      .scroll

        cmp     [.utf8], 'a'
        je      .scrollback

        cmp     [.utf8], 'r'
        je      .refresh

        cmp     [.utf8], 't'
        je      .refresh2

        return

.scroll:
        stdcall Scroll, 0
        return

.scrollback:

        mov     eax, [incX]
        mov     ecx, [incY]
        neg     eax
        neg     ecx

        mov     [incX], eax
        mov     [incY], ecx
        mov     [dist], 1000
        jmp     .scroll

.refresh:
        exec    [.self], TWindow:RectChanged2, 0
        return

.refresh2:
        mov     eax, [.self]
        stdcall _RefreshWindowRect, [eax+TWindow.handle], 0, 0, [eax+TWindow._width], [eax+TWindow._height]
        return


endp



proc Scroll, .application


.rect1 dd ?
begin
        pushad

        mov     esi, [frmMain]
        test    esi, esi
        jz      .finish
................................................................................

        stdcall LockImg, ebx
        jc      .finish

        mov     edi, [imgBackground]
        stdcall LockImg, edi

; First restore the text rectangle

        stdcall BlendImageTileWrap, ebx, 32, 32, 128, 64, edi







; scroll the destination image.

        mov     edx, [ebx+TImage.wrapW]
        mov     ecx, [ebx+TImage.orgX]
        add     ecx, [incX]
        jns     @f
        add     ecx, edx
@@:
        cmp     ecx, edx
        jb      @f
        sub     ecx, edx
@@:
        mov     [ebx+TImage.orgX], ecx

        mov     edx, [ebx+TImage.wrapH]
        mov     ecx, [ebx+TImage.orgY]
        add     ecx, [incY]
        jns     @f
        add     ecx, edx
@@:
        cmp     ecx, edx
        jb      @f
        sub     ecx, edx
@@:
        mov     [ebx+TImage.orgY], ecx

; scroll the source image


        mov     edx, [edi+TImage.wrapW]







        mov     ecx, [edi+TImage.orgX]
        add     ecx, [incX]
        jns     @f
        add     ecx, edx
@@:
        cmp     ecx, edx
        jb      @f
        sub     ecx, edx
@@:
        mov     [edi+TImage.orgX], ecx

        mov     edx, [edi+TImage.wrapH]
        mov     ecx, [edi+TImage.orgY]
        add     ecx, [incY]
        jns     @f
        add     ecx, edx
@@:
        cmp     ecx, edx
        jb      @f
        sub     ecx, edx
@@:
        mov     [edi+TImage.orgY], ecx

; then paint the fixed rectangle again

        stdcall DrawSolidRect, ebx, 32, 32, 128, 64, $ffffffff
        pushad

        stdcall StrDupMem, "FPS: "
        mov     edx, eax
        stdcall NumToStr, [fps], ntsDec or ntsUnsigned
        stdcall StrCat, edx, eax
        stdcall StrDel, eax
        push    edx
        stdcall StrPtr, edx
        stdcall DrawString, ebx, eax, [eax+string.len], 48, 48, [GUI.DefaultFont], $ff000000
        stdcall StrDel ; from the stack
        popad

        mov     eax, [incX]
        mov     ecx, [ebx+TImage.wrapW]
        sub     ecx, eax
        test    eax, eax
        jz      .x_ok
        jns     .ix_ok
        neg     eax
        xor     ecx, ecx
.ix_ok:
        stdcall BlendImageTileWrap, ebx, ecx, 0, eax, [ebx+TImage.wrapH], edi

.x_ok:
        mov     eax, [incY]
        mov     ecx, [ebx+TImage.wrapH]
        sub     ecx, eax
        test    eax, eax
        jz      .y_ok
        jns     .iy_ok
        neg     eax
        xor     ecx, ecx
.iy_ok:
        stdcall  BlendImageTileWrap, ebx, 0, ecx, [ebx+TImage.wrapW], eax, edi
.y_ok:

        stdcall UnlockImg, edi
        stdcall UnlockImg, ebx

        stdcall _RefreshWindowRect, [esi+TWindow.handle], 0, 0,[esi+TWindow._width], [esi+TWindow._height]
        stdcall Randomize

.finish:
        popad
        return