{ $Id$ This file is part of the Free Pascal run time library. Copyright (c) 1993,97 by the Free Pascal development team See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} procedure DrawPattern(x1,x2,y:integer); begin asm movswl x1,%ebx movswl x2,%ecx movswl y,%edx subl %ebx,%ecx incl %ecx movl _X_ARRAY(,%ebx,4),%eax movl _Y_ARRAY(,%edx,4),%edi // { Offset in %edi } addl %eax,%edi andl _WINLOMASK,%edi andl $0x7,%edx // { y and $7 } shll $0x5,%edx // { y * 8 * sizeof(longint) } leal _PATTERNBUFFER,%esi // addl %edx,%esi // { Offset in Patternbuffer } movl $0x7,%edx addl _WBUFFER,%edi pushw %es movw _SEG_WRITE,%ax movw %ax,%es testw $1,_AKTWRITEMODE jnz pl_xord pl_movd: testw $1,_BYTESPERPIXEL jz pl_movdw .align 4,0x90 pl_movdb: andl %edx,%ebx movb (%esi,%ebx,4),%al movb %al,%es:(%edi) incl %edi incl %ebx decl %ecx jnz pl_movdb jz pl_d_exit .align 4,0x90 pl_movdw: andl %edx,%ebx movw (%esi,%ebx,4),%ax movw %ax,%es:(%edi) addl $2,%edi incl %ebx decl %ecx jnz pl_movdw jz pl_d_exit pl_xord: testw $1,_BYTESPERPIXEL jz pl_xordw .align 4,0x90 pl_xordb: andl %edx,%ebx movb (%esi,%ebx,4),%al xorb %al,%es:(%edi) incl %edi incl %ebx decl %ecx jnz pl_xordb jz pl_d_exit .align 4,0x90 pl_xordw: andl %edx,%ebx movw (%esi,%ebx,4),%ax xorw %ax,%es:(%edi) addl $2,%edi incl %ebx decl %ecx jnz pl_xordw pl_d_exit: popw %es pl_exit: end; end; procedure PatternLine(x1,x2,y:integer); var bank1,bank2 : longint; ofs1,ofs2 : longint; diff : integer; viewport : ViewPortType; begin x1:= x1 + aktviewport.x1 ; y:= y + aktviewport.y1 ; x2:= x2 + aktviewport.x1 ; if aktviewport.clip then viewport:=aktviewport else viewport:=aktscreen; if (y < viewport.y1) or (y > viewport.y2) then exit; if x1 > x2 then begin diff:=x2; x2:=x1; x1:=diff; end; if (x1> viewport.x2) or (x2< viewport.x1) then exit; if x1 < viewport.x1 then x1:=viewport.x1; if x2 > viewport.x2 then x2:=viewport.x2; ofs1:= Y_ARRAY[y]; ofs2:= ofs1 + X_ARRAY[x2]; ofs1:= ofs1 + X_ARRAY[x1]; bank1:=ofs1 shr winshift; bank2:=ofs2 shr winshift; if bank1 <> AW_BANK then begin Switchbank(bank1); AW_BANK:=bank1; end; if bank1 <> bank2 then begin diff:=(((bank2 shl winshift)-ofs1) div BytesPerPixel)+x1; DrawPattern(x1,diff-1,y); Switchbank(bank2); AW_BANK:=bank2; DrawPattern(diff,x2,y); end else DrawPattern(x1,x2,y); end; procedure HorizontalLine(x1,x2,y:integer); { without bankswitching } begin asm movw %es,%dx movzwl y,%ebx movzwl x1,%eax movzwl x2,%ecx incl %ecx movl _X_ARRAY(,%eax,4),%eax movl _X_ARRAY(,%ecx,4),%ecx movl _Y_ARRAY(,%ebx,4),%edi // { Offset in %edi } subl %eax,%ecx // { Counter } addl %eax,%edi andl _WINLOMASK,%edi movl _AKTCOLOR,%eax movzwl _AKTWRITEMODE,%esi addl _WBUFFER,%edi movw _SEG_WRITE,%bx movw %bx,%es testl %esi,%esi // { Writemode ? } jnz hl_xor shrl %ecx jnc _movw stosb _movw: shrl %ecx jnc _movd stosw _movd: rep stosl jmp hl_exit hl_xor: // ------------------------------------------------- movl $4,%esi shrl %ecx jnc hl_xorw xorb %al,%es:(%edi) incl %edi hl_xorw: shrl %ecx jnc hl_xord xorw %ax,%es:(%edi) addl $2,%edi hl_xord: jecxz hl_exit .align 4,0x90 hl_xorloop: xorl %eax,%es:(%edi) addl %esi,%edi decl %ecx jnz hl_xorloop hl_exit: movw %dx,%es end; end; procedure Line(x1,y1,x2,y2: integer); var dx,dy,d : longint; i,j : integer; ofs,ofs2 : longint; i1,i2,ix : longint; x,y : Integer; flag,dontcheck : Boolean; viewport : ViewPortType; begin x1:= x1 + aktviewport.x1 ; y1:= y1 + aktviewport.y1 ; x2:= x2 + aktviewport.x1 ; y2:= y2 + aktviewport.y1 ; if aktviewport.clip then viewport:=aktviewport else viewport:=aktscreen; { ************ Horizontalline ************** } if y1=y2 then begin if x1>x2 then begin d:=x1; x1:=x2; x2:=d; end; if aktlineinfo.thickness=3 then y1:=y1-1; i:=0; if x1 < viewport.x1 then x1:=viewport.x1; if x2 > viewport.x2 then x2:=viewport.x2; if (y1 > viewport.y2) or (x1 > x2 ) then exit; repeat if (y1 >= viewport.y1) and (y1 <=viewport.y2) then begin ofs:= Y_ARRAY[y1]; ofs2:=ofs+X_ARRAY[x2]; ofs:= ofs+X_ARRAY[x1]; i1:=ofs shr winshift; i2:=ofs2 shr winshift; if i1 <> aw_bank then begin switchbank(i1); aw_bank:=i1; end; if i1=i2 then Horizontalline(x1,x2,y1) else begin dx:=((i2 shl winshift)-ofs) div BytesPerPixel; horizontalline(x1,x1+dx-1,y1); Switchbank(i2); AW_BANK:=i2; horizontalline(dx+x1,x2,y1); end; end; i:=i+1; y1:=y1+1; until i=aktlineinfo.thickness; exit; end; { *********** End Horizontalline *********** } if y1 > y2 then begin x:=x1; x1:=x2; x2:=x; y:=y1; y1:=y2; y2:=y; end; { ************** Verticalline ************** } if x1=x2 then begin if y1 < viewport.y1 then y1:=viewport.y1; if y2 > viewport.y2 then y2:=viewport.y2; if ( y1 > y2) or (x1 < viewport.x1) or (x1 > viewport.x2) then exit; ofs:= Y_Array[y2]+X_Array[x1]; ofs2:=Y_Array[y1]+X_Array[x1]; while ofs >= ofs2 do begin pixel(ofs); if aktlineinfo.thickness=3 then begin if x1>viewport.x1 then pixel(ofs-1); if x1x2 then ix:=-1 else ix:= 1; if dx=viewport.y1) and (y2<=viewport.y2) and (x1>=viewport.x1) and (x1<=viewport.x2) and (x2>=viewport.x1) and (x2<=viewport.x2); if aktlineinfo.thickness=3 then { *************************************** } { **** Thickness=3 with rangechecking *** } { *************************************** } begin repeat for i:=y1-1 to y1+1 do for j:=x1-1 to x1+1 do if (i>=viewport.y1) and (j>=viewport.x1) and (j<=viewport.x2) and (i<=viewport.y2) then pixel(X_ARRAY[j]+Y_ARRAY[i]); if d < 0 then begin if Flag then y1:=y1+1 else x1:=x1+ix; d:=d+i1; end else begin d:=d-i2; x1:=x1+ix; y1:=y1+1; end; dx:=dx-1; until ( dx=0 ) or ( y1 > viewport.y2 ) end else if dontcheck then { *************************************** } { ** Thickness=1 without rangechecking ** } { *************************************** } begin asm pushw %gs movw _SEG_WRITE,%ax movw %ax,%gs // { ScreenSelector } // selfmodify to speedup Code xorl %ebx,%ebx movl ix,%eax testl %eax,%eax jns line1_inc movl $0x08,%ebx line1_inc: addl $0x43,%ebx // Opcode incl %ebx movb %bl,inc_dec1 movb %bl,inc_dec2 movl i1,%eax movl %eax,i1long1 movl %eax,i1long2 movl i2,%eax movl %eax,i2long movl _WBUFFER,%eax movl %eax,.Lwbuffer movl _WINSHIFT,%eax movb %al,.Lwinshift movl _WINLOMASK,%eax movl %eax,.Lwinlomask movb $0x90,operandprefix // Opcade nop testw $1,_AKTWRITEMODE jnz line1XOR movb $0x88,linemode // Opcode movb jmp linedepth line1XOR: movb $0x30,linemode // Opcode xorb linedepth: testw $1,_BYTESPERPIXEL jnz is_byte movb $0x66,operandprefix // Prefix for operandsize incb linemode // incr. for wordacces is_byte: movl dx,%ecx movl _AKTCOLOR,%eax movzwl y1,%esi movzwl x1,%ebx movswl d,%edx //----------------// // Linemainloop // //----------------// .align 4,0x90 line1_loop: pushl %ecx pushl %eax movl _Y_ARRAY(,%esi,4),%edi addl _X_ARRAY(,%ebx,4),%edi movl %edi,%eax .byte 0x81,0xe7 // andl ..,%edi .Lwinlomask: // .long 0x88888888 // _WINLOMASK .byte 0xc1,0xe8 // shrl ..,%eax .Lwinshift: // .byte 0x88 // _WINSHIFT pushl %edi cmpl _AW_BANK,%eax je line1_dontswitch pushl %ebx pushl %edx pushl %esi movl %eax,_AW_BANK // newbank pushl %eax movl _BANKSWITCHPTR,%eax call %eax popl %esi popl %edx popl %ebx .align 4,0x90 line1_dontswitch: popl %edi popl %eax popl %ecx .byte 0x81,0xc7 // addl ..,%edi .Lwbuffer: // .long 0x88888888 // _WBUFFER operandprefix: .byte 0x90 // Operandprefix (nop for Byte,$66 for Word) .byte 0x65 // Segmentprefix %gs: linemode: .byte 0x88,0x07 // modified OpCode,%edi decl %ecx jz line1_end testl %edx,%edx // { if d < 0 then } jns is_positive testb $1,flag // { if flag then } jz no_flag incl %esi // { y1:=y1+1 } .byte 0x81,0xc2 i1long1: .long 0x88888888 // { d:=d+i1 } jmp line1_loop .align 4,0x90 no_flag: inc_dec1: .byte 0x88 // { x1:=x1+ix } .byte 0x81,0xc2 i1long2: .long 0x88888888 // { d:=d+i1 } jmp line1_loop .align 4,0x90 is_positive: inc_dec2: .byte 0x88 // { x1:=x1+ix } incl %esi // { y1:=y1+1 } .byte 0x81,0xea i2long: .long 0x88888888 // { d:=d-i2 } jmp line1_loop line1_end: popw %gs end; end else { *************************************** } { **** Thickness=1 with rangechecking *** } { *************************************** } begin repeat if y1 > viewport.y2 then exit; if (y1>=viewport.y1) and (x1>=viewport.x1) and (x1<=viewport.x2) then pixel(Y_ARRAY[y1]+X_ARRAY[x1]); if d < 0 then begin if Flag then y1:=y1+1 else x1:=x1+ix; d:=d+i1; end else begin d:=d-i2; x1:=x1+ix; y1:=y1+1; end; dx:=dx-1; until dx=0 ; end; end; procedure MoveTo(x,y : integer); begin _graphresult:=grOk; if not isgraphmode then begin _graphresult:=grnoinitgraph; exit; end; curx:=x; cury:=y; end; procedure MoveRel(dx,dy : integer); begin _graphresult:=grOk; if not isgraphmode then begin _graphresult:=grnoinitgraph; exit; end; curx:=curx+dx; cury:=cury+dy; end; procedure LineTo(x,y : integer); begin _graphresult:=grOk; if not isgraphmode then begin _graphresult:=grnoinitgraph; exit; end; Line(curx,cury,x,y); MoveTo(x,y); end; procedure LineRel(dx,dy : integer); begin _graphresult:=grOk; if not isgraphmode then begin _graphresult:=grnoinitgraph; exit; end; Line(curx,cury,curx+dx,cury+dy); curx:=curx+dx; cury:=cury+dy; end; procedure SetLineStyle(LineStyle : word;pattern : word;thickness : word); const linepatterns : array[0..3] of word = ($ffff,$aaaa,$fafa,$ffff); begin if (linestyle<0) or (linestyle>4) or ((thickness<>1) and (thickness<>3)) then begin _graphresult:=grerror; exit; end; aktlineinfo.linestyle:=linestyle; if aktlineinfo.linestyle=UserBitLn then aktlineinfo.pattern:=pattern else aktlineinfo.pattern:=linepatterns[aktlineinfo.linestyle]; aktlineinfo.thickness:=thickness; end; procedure DrawPoly(points : word;var polypoints); type ppointtype = ^pointtype; var i : longint; begin _graphresult:=grOk; if not isgraphmode then begin _graphresult:=grnoinitgraph; exit; end; line(ppointtype(@polypoints)[points-1].x, ppointtype(@polypoints)[points-1].y, ppointtype(@polypoints)[0].x, ppointtype(@polypoints)[0].y); for i:=0 to points-2 do line(ppointtype(@polypoints)[i].x, ppointtype(@polypoints)[i].y, ppointtype(@polypoints)[i+1].x, ppointtype(@polypoints)[i+1].y); end; { $Log$ Revision 1.2 1998-09-02 08:16:00 pierre * local asm labels with global variable names removed !! Revision 1.1.1.1 1998/03/25 11:18:42 root * Restored version Revision 1.4 1998/03/03 22:48:43 florian + graph.drawpoly procedure + putimage with xorput uses mmx if available Revision 1.3 1998/01/26 11:58:18 michael + Added log at the end Working file: rtl/dos/ppi/line.ppi description: ---------------------------- revision 1.2 date: 1997/12/01 12:21:31; author: michael; state: Exp; lines: +14 -0 + added copyright reference in header. ---------------------------- revision 1.1 date: 1997/11/27 08:33:51; author: michael; state: Exp; Initial revision ---------------------------- revision 1.1.1.1 date: 1997/11/27 08:33:51; author: michael; state: Exp; lines: +0 -0 FPC RTL CVS start ============================================================================= }