Author |
Topic: Using GDIP with assembler (Read 136 times) |
|
svein
New Member
member is offline


Posts: 15
|
 |
Using GDIP with assembler
« Thread started on: Oct 25th, 2017, 01:06am » |
|
Hello Richard. I hope you can help with a little problem.
It's about drawing a line in GDI+ from assembler code.
In the supplied demo, two figures are drawn, one by assembler and one by the regular library call, using the same pen for both. With a width of one, they look the same, but as the width increases, the assembler drawn figure seems to use a different pen style. Any idea why ?
The @memhdc% parameter causes a crash if included in the assembler call to 'GdipDrawLine'. Any idea why ?
In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library. And it still works, how come ??
This is for windows 10. Svein
Code: INSTALL @lib$+"GDIPLIB" : PROC_gdipinit ON CLOSE PROCexit : QUIT Pen%=FN_gdipcreatepen(&FF000000,0,1) PROC_asm : OFF ON TIME PROCnewpen : RETURN *REFRESH OFF REPEAT : CLS Posx=500 : Posy=500 A%+=1 : Angle=A% FOR I%=1 TO 12 Angle+=30 FOR J%=1 TO 6 Posx+=100*SINRAD(Angle) Posy+=100*COSRAD(Angle) CALL antiline PROC_gdipline(Pen%,oldx+400,oldy,Posx+400,Posy) oldx=Posx : oldy=Posy Angle-=60 NEXT NEXT *REFRESH WAIT 0 UNTIL 0 DEF PROCnewpen PRIVATE width,adj IF width=0 THEN width=2 : adj=0.25 width+=adj IF width>5 OR width<1 THEN adj=-adj PROC_gdipdeletepen(Pen%) Pen%=FN_gdipcreatepen(&FF204080,0,width) ENDPROC DEF PROC_gdipline(P%, x1, y1, x2, y2) LOCAL rc{} DIM rc{l%,t%,r%,b%} PROC_bbc2api(x1,y1) PROC_bbc2api(x2,y2) SYS "SetBoundsRect", @memhdc%, 0, 5 SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc% SYS "GetBoundsRect", @memhdc%, rc{}, 0 SYS "OffsetRect", rc{}, -@ox%, -@oy% SYS "InvalidateRect", @hwnd%, rc{}, 0 ENDPROC DEF PROC_asm LOCAL var%,code%,pass%,P%,L%,size% size%=2048 DIM var% NOTEND AND 3, var% 1023 DIM code% NOTEND AND 2047, code% size%-1 FOR pass%=8 TO 10 STEP 2 P%=var% : L%=code%-1 [OPT pass% .temprc dd 0 : dd 0 : dd 0 : dd 0 .tempx dd 0 .tempy dd 0 .grhdc dd 0 .two dd 2 ] P%=code% : L%=code%+size%-1 [OPT pass% .antiline cld finit ;SYS "SetBoundsRect", @memhdc%, 0, 5 push 5 ; DCB_ENABLE OR DCB_RESET push 0 push @memhdc% call "SetBoundsRect" ; ;SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc% ; push @memhdc% fld tbyte [^Posy] : call y2api : fstp dword [tempy] : push [tempy] ;real80 to real32 for gdi+ fld tbyte [^Posx] : call x2api : fstp dword [tempx] : push [tempx] fld tbyte [^oldy] : call y2api : fstp dword [tempy] : push [tempy] fld tbyte [^oldx] : call x2api : fstp dword [tempx] : push [tempx] push Pen% push [grhdc] call `GdipDrawLine` ; ;SYS "GetBoundsRect", @memhdc%, rc{}, 0 push 0 push temprc push @memhdc% call "GetBoundsRect" ; ;SYS "OffsetRect", rc{}, -@ox%, -@oy% push -@oy% push -@ox% push temprc call "OffsetRect" ; ;SYS "InvalidateRect", @hwnd%, rc{}, 0 push 0 push temprc push @hwnd% call "InvalidateRect" ret ; .y2api ;y=@vdu%!212-(y+@vdu%!4)/2 fiadd dword [@vdu%+4] fidiv dword [two] fild dword [@vdu%+212] fsub st0,st1 ret ; .x2api ;x=(x+@vdu%!0)/2 fiadd dword [@vdu%] fidiv dword [two] ret ] NEXT pass% !grhdc=FN_gdipg ENDPROC DEF PROCexit ON TIME OFF : WAIT 30 PROC_gdipdeletepen(Pen%) PROC_gdipexit ENDPROC
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: Using GDIP with assembler
« Reply #1 on: Oct 25th, 2017, 10:20am » |
|
on Oct 25th, 2017, 01:06am, svein wrote: As far as I can see, there are two principal faults in your code:
Pen% is a variable (it's modified in PROCnewpen) but your assembler code treats it as a constant. To fix this:
Change this Code: To this Code: Your y2api subroutine corrupts the floating-point stack (there are more 'pushes' than 'pops'). To fix this:
Change this Code: To this Code: Quote:| In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library. And it still works, how come ?? |
|
It doesn't still work, or at least not reliably. The @memhdc% activates the Critical Section that protects against concurrent access to the DC from two different threads (Windows DCs are not thread-safe and must be accessed from only one thread at a time). If you omit the @memhdc% you are trusting to luck that the interpreter thread and the GUI thread will not try to access the DC at the same time, which would fail.
Richard.
|
|
|
|
svein
New Member
member is offline


Posts: 15
|
 |
Re: Using GDIP with assembler
« Reply #2 on: Oct 26th, 2017, 06:59am » |
|
Thank you ! Went over the code a million times without spotting the errors. Svein
|
|
Logged
|
|
|
|
|