|
|
1.1 ! root 1: ;---------------------------Module-Header------------------------------; ! 2: ; Module Name: fastline.asm ! 3: ; ! 4: ; This module draws solid lines using the line hardware of the S3. ! 5: ; It handles entirely unclipped lines, or lines clipped to a single ! 6: ; rectangle by using the S3's hardware clipping. ! 7: ; ! 8: ; All lines that have integer end-points are drawn directly using the ! 9: ; line hardware, and any lines having fractional end-points and are ! 10: ; less than 256 pels long are also drawn directly by the line hardware. ! 11: ; (Fractional end-point lines require 4 more bits of precision from the ! 12: ; DDA hardware than do integer end-point lines, and the S3 has but 13 ! 13: ; bits to use. Lines longer than 255 pels are punted to the general ! 14: ; purpose strip routines, which won't overflow the hardware). ! 15: ; ! 16: ; There are a number of ways unclipped lines can be sped up on the S3: ! 17: ; ! 18: ; 1) Optimize NT's GDI. This isn't an option for everybody. ! 19: ; ! 20: ; 2) Use memory-mapped I/O. ! 21: ; ! 22: ; 3) If you can't use memory-mapped I/O, you can at least minimize ! 23: ; outs and ins because they are so painfully expensive. One ! 24: ; way to do this is to amortize the cost of the in used for checking ! 25: ; the FIFO: do one in to make sure a large number of entries on ! 26: ; the FIFO are free (perhaps 6), then do the next 6 outs without ! 27: ; having to check the FIFO. ! 28: ; ! 29: ; This will be a win on figures not requiring many outs (such as when ! 30: ; radial lines are drawn as with a rectangle), assuming the hardware ! 31: ; isn't always being overdriven. ! 32: ; ! 33: ; 4) In conjunction with 3) above, since short integer lines occur so ! 34: ; frequently with CAD programs, it would be beneficial to use short- ! 35: ; stroke vectors to do those lines, as they could reduce the number ! 36: ; of outs required. Perhaps any line 10 pels or shorter could be ! 37: ; output by using an array lookup to determine the short stroke vectors ! 38: ; needed to represent that line. ! 39: ; ! 40: ; 5) Numerous other things I haven't thought of. ! 41: ; ! 42: ; Other improvements that should be done to make lines faster in general: ! 43: ; ! 44: ; 1) Simple clipping should be improved. Currently, we simply set the ! 45: ; clip rectangle and let the hardware do everything. We should at least ! 46: ; perform a trivial clip test to see if there's no chance the line ! 47: ; intersects the clip rectangle. ! 48: ; ! 49: ; Also, for single lines it's expensive to do the 4 outs required to ! 50: ; set the S3's clip rectangle, draw the line, then do 4 outs to reset ! 51: ; the clip rectangle again. In those cases, it would be faster to do the ! 52: ; clipping entirely in software. ! 53: ; ! 54: ; 2) This code can be enhanced to also handle styled lines, and to do ! 55: ; complex clipping more efficiently than the strips routines. ! 56: ; ! 57: ; 3) It is possible to derive the mathematical algorithm for drawing any ! 58: ; GIQ line in NT's 32 bit space using the limited bit precision of the ! 59: ; S3's hardware. What this means is that absolutely any GIQ line can ! 60: ; be drawn precisely with at most two drawing commands to the line ! 61: ; hardware (and so the strips line drawing routine could be eliminated ! 62: ; entirely). Just be careful of your math... ! 63: ; ! 64: ; 4) Numerous other things I haven't thought of. ! 65: ; ! 66: ; Copyright (c) 1992-1993 Microsoft Corporation ! 67: ;-----------------------------------------------------------------------; ! 68: ! 69: .386 ! 70: ! 71: .model small,c ! 72: ! 73: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT ! 74: assume fs:nothing,gs:nothing ! 75: ! 76: .xlist ! 77: include stdcall.inc ;calling convention cmacros ! 78: include i386\strucs.inc ! 79: include i386\lines.inc ! 80: .list ! 81: ! 82: ; Line coordinates are given in 28.4 fixed point format: ! 83: ! 84: F equ 16 ! 85: FLOG2 equ 4 ! 86: ! 87: ; The S3's hardware can have 13 bits of significance for the error and ! 88: ; step terms: ! 89: ! 90: NUM_DDA_BITS equ 13 ! 91: ! 92: ; GIQ lines have to dedicate 4 bits to the fractional term, so the largest ! 93: ; delta we can handle for GIQ lines is calculated as follows (scaled by F ! 94: ; so we can do the test in GIQ coordinates), and remembering that one bit ! 95: ; has to be used as a sign bit: ! 96: ! 97: MAX_GIQ_DELTA equ (((1 shl (NUM_DDA_BITS - 5)) - 1) * F) ! 98: ! 99: ; The following values must match those in winddi.h! ! 100: ! 101: PD_BEGINSUBPATH equ 00000001h ! 102: PD_ENDSUBPATH equ 00000002h ! 103: PD_RESETSTYLE equ 00000004h ! 104: PD_CLOSEFIGURE equ 00000008h ! 105: PD_BEZIERS equ 00000010h ! 106: ! 107: PATHDATA struc ! 108: ! 109: pd_flags dd ? ! 110: pd_count dd ? ! 111: pd_pptfx dd ? ! 112: ! 113: PATHDATA ends ! 114: ! 115: ;-------------------------------------------------------------------------; ! 116: ; I felt a compelling need to use 'ebp' as a 7th general register, and we ! 117: ; have no nifty macros for dereferencing frame variables off 'esp'. So ! 118: ; with this structure I am rolling my own stack frame: ! 119: ! 120: STATE_MEM_SIZE equ 4 ;4 dwords ! 121: PROC_MEM_SIZE equ 7 ;7 dwords ! 122: ! 123: STACK_FRAME struc ! 124: ! 125: ; State variables (don't add/delete fields without modifying STATE_MEM_SIZE!) ! 126: ! 127: sf_ulOurEbp dd ? ;useful for debugging ! 128: sf_ulOriginalEbx dd ? ! 129: sf_ulOriginalEdi dd ? ! 130: sf_ulOriginalEsi dd ? ! 131: ! 132: ; Frame variables (feel free to add/delete fields): ! 133: ! 134: sf_y0 dd ? ;GIQ variables ! 135: sf_y1 dd ? ! 136: sf_x1 dd ? ! 137: sf_ptlOrg db (size POINTL) dup (?) ! 138: ;our origin for normalizing the line ! 139: sf_ptfxLast db (size POINTL) dup (?) ! 140: ;the most recent point ! 141: sf_ptfxStartFigure db (size POINTL) dup (?) ! 142: ;the figure's 1st point ! 143: sf_bMore dd ? ;more path records to get? ! 144: sf_pptfxEnd dd ? ;points to last point in record ! 145: sf_pptfx dd ? ;points to current point ! 146: sf_pd db (size PATHDATA) dup (?) ! 147: ;pathdata structure ! 148: sf_ptfxStart db (size POINTL) dup (?) ! 149: ;temporary spot for saving start point ! 150: sf_ptfxEnd db (size POINTL) dup (?) ! 151: ;temporary spot for saving end point ! 152: sf_ulCmd dd ? ;S3 draw command ! 153: sf_cPels dd ? ;length of line in pels ! 154: sf_bSetCP dd ? ;1 if first line in figure, 0 otherwise ! 155: sf_ulLastLength dd ? ;last value set as LINE_MAX ! 156: sf_ulErrorTerm dd ? ;error term for line ! 157: ! 158: ; Procedure variables (don't add/delete fields without modifying ! 159: ; PROC_MEM_SIZE!) ! 160: ! 161: sf_ulOriginalEbp dd ? ! 162: sf_ulOriginalReturn dd ? ! 163: sf_ppdev dd ? ! 164: sf_ppo dd ? ! 165: sf_prclClip dd ? ! 166: sf_apfn dd ? ! 167: sf_flags dd ? ! 168: ! 169: STACK_FRAME ends ! 170: ! 171: .data ! 172: ! 173: EXTRNP PATHOBJ_bEnum,8 ! 174: EXTRNP bLines,36 ! 175: ! 176: .code ! 177: ! 178: ROUND_X_DOWN equ 01h ! 179: ROUND_Y_DOWN equ 02h ! 180: ROUND_SLOPE_ONE equ 04h ! 181: ROUND_X_AND_Y_DOWN equ (ROUND_X_DOWN + ROUND_Y_DOWN) ! 182: ROUND_X_DOWN_SLOPE_ONE equ (ROUND_X_DOWN + ROUND_SLOPE_ONE) ! 183: ROUND_Y_DOWN_SLOPE_ONE equ (ROUND_Y_DOWN + ROUND_SLOPE_ONE) ! 184: ! 185: ;--------------------------------Macro----------------------------------; ! 186: ; GIQ flags ! 187: ; ! 188: ; This macros computes the start pixel, the number of pixels to ! 189: ; be lit, and the initial error term given a GIQ line. The line must ! 190: ; have already been normalized such that dM >= dN, dN >= 0. ! 191: ; ! 192: ; Input: ebx - M0 ! 193: ; ecx - N0 ! 194: ; esi - dM ! 195: ; edi - dN ! 196: ; Trashes: ! 197: ; eax, edx ! 198: ; [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y ! 199: ; Output: ! 200: ; [esp].sf_x1 - x-coordinate of last pixel (exclusive) ! 201: ; ebx - x-coordinate of first pixel ! 202: ; ecx - error term ! 203: ; esi - dM ! 204: ; edi - dN ! 205: ; ebp - y-coordinate of first pixel ! 206: ;-----------------------------------------------------------------------; ! 207: ! 208: GIQ macro flags ! 209: local compute_x1, compute_error_term ! 210: ! 211: ; We normalize our coordinate system so that if the start point is ! 212: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)): ! 213: ! 214: mov eax,ebx ! 215: mov ebp,ecx ! 216: sar eax,FLOG2 ! 217: sar ebp,FLOG2 ! 218: mov [esp].sf_ptlOrg.ptl_x,eax ! 219: ;ptlOrg.x = floor(M0 / F) ! 220: mov [esp].sf_ptlOrg.ptl_y,ebp ! 221: ;ptlOrg.y = floor(N0 / F) ! 222: ! 223: ; Calculate the correct [esp].sf_x1: ! 224: ! 225: lea ebp,[ecx + edi] ;ebp = N1 ! 226: and ebp,F - 1 ! 227: ! 228: if (flags AND ROUND_X_DOWN) ! 229: ! 230: if (flags AND ROUND_SLOPE_ONE) ! 231: lea edx,[ebx + esi] ! 232: and edx,F - 1 ;edx = M1 ! 233: sub edx,8 ! 234: cmp edx,ebp ;cmp M1 - 8, N1 ! 235: jne short compute_x1 ! 236: ! 237: lea edx,[ebx + esi] ! 238: sar edx,FLOG2 ! 239: jmp short compute_error_term ! 240: endif ! 241: ! 242: compute_x1: ! 243: ! 244: cmp ebp,1 ! 245: sbb ebp,8 ;N1 -= 8 ! 246: else ! 247: sub ebp,8 ;N1 -= 8 ! 248: endif ! 249: sbb eax,eax ! 250: xor ebp,eax ! 251: sub ebp,eax ;N1 = ABS(N1) ! 252: ! 253: lea edx,[ebx + esi] ! 254: mov eax,edx ! 255: sar edx,FLOG2 ! 256: and eax,F - 1 ! 257: jz short @f ;special case for M1 == 0 ! 258: cmp eax,ebp ;cmp M1, N1 ! 259: sbb edx,-1 ;edx is now one pixel past the actual ! 260: @@: ; end coordinate (note that it hasn't ! 261: ; been affected by the origin shift) ! 262: ! 263: compute_error_term: ! 264: ! 265: ; ebx = M0 ! 266: ; ecx = N0 ! 267: ; edx = x1 ! 268: ; esi = dM ! 269: ; edi = dN ! 270: ! 271: and ecx,F - 1 ! 272: mov [esp].sf_x1,edx ;save x1 ! 273: ! 274: ; Calculate our error term for x = 0. ! 275: ; ! 276: ; NOTE: Since this routine is used only for lines that are unclipped, we ! 277: ; are guaranteed by our screen size that the values will be far less ! 278: ; than 32 bits in significance, and so we don't worry about overflow. ! 279: ; If this is used for clipped lines, these multiplies will have to ! 280: ; be converted to give 64 bit results, because we can have 36 bits of ! 281: ; significance! ! 282: ! 283: ! 284: lea ebp,[ecx + 8] ;ebp = N0 + 8 ! 285: mov eax,esi ! 286: imul eax,ebp ;eax = dM * (N0 + 8) ! 287: mov ebp,edi ! 288: ! 289: ; We have to special case when M0 is 0 -- we know x0 will be zero. ! 290: ; So we jump ahead a bit to a place where 'ebx' is assumed to contain ! 291: ; x0 -- and it just so happens 'ebx' is zero in this case: ! 292: ! 293: and ebx,F - 1 ! 294: jz short @f ! 295: imul ebp,ebx ;ebp = dN * M0 ! 296: sub eax,ebp ! 297: ! 298: ; Calculate the x-coordinate of the first pixel: ! 299: ! 300: if (flags AND ROUND_X_DOWN) ! 301: ! 302: if (flags AND ROUND_SLOPE_ONE) ! 303: cmp ecx,8 ! 304: sbb ecx,-1 ! 305: endif ! 306: ! 307: cmp ecx,1 ! 308: sbb ecx,8 ;N0 -= 8 ! 309: else ! 310: sub ecx,8 ;N0 -= 8 ! 311: endif ! 312: sbb ebp,ebp ! 313: xor ecx,ebp ! 314: sub ecx,ebp ;N0 = ABS(N0) ! 315: cmp ebx,ecx ! 316: sbb ebx,ebx ! 317: not ebx ;ebx = -x0 ! 318: ! 319: ; Now adjust the error term accordingly: ! 320: ! 321: @@: ! 322: if (flags AND ROUND_Y_DOWN) ! 323: dec eax ! 324: endif ! 325: sar eax,FLOG2 ;eax = floor((N0 + 8) dM - M0 dN] / 16) ! 326: ! 327: mov ecx,[esp].sf_ptlOrg.ptl_x ! 328: mov ebp,[esp].sf_ptlOrg.ptl_y ! 329: ! 330: sub ecx,ebx ;ecx = ptlOrg.ptl_x + x0 ! 331: ! 332: and ebx,edi ! 333: add ebx,eax ! 334: sub ebx,esi ;ebx = dN * x0 + initial error - dM ! 335: jl short @f ;if the error term >= 0, we have to ! 336: sub ebx,esi ; add 1 to the y position and subtract ! 337: inc ebp ; dM off again ! 338: @@: ! 339: xchg ebx,ecx ! 340: ! 341: endm ! 342: ! 343: ;--------------------------------Macro----------------------------------; ! 344: ; GIQR flags ! 345: ; ! 346: ; Same as above, except it handles flips about the line x = y. ! 347: ; ! 348: ; Input: ebx - M0 ! 349: ; ecx - N0 ! 350: ; esi - dM ! 351: ; edi - dN ! 352: ; Trashes: ! 353: ; eax, edx ! 354: ; [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y ! 355: ; Output: ! 356: ; [esp].sf_y1 - y-coordinate of last pixel (exclusive) ! 357: ; ebx - x-coordinate of first pixel ! 358: ; ecx - error term ! 359: ; esi - dM ! 360: ; edi - dN ! 361: ; ebp - y-coordinate of first pixel ! 362: ;-----------------------------------------------------------------------; ! 363: ! 364: GIQR macro flags ! 365: ! 366: ; We normalize our coordinate system so that if the start point is ! 367: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)): ! 368: ! 369: mov eax,ebx ! 370: mov ebp,ecx ! 371: sar eax,FLOG2 ! 372: sar ebp,FLOG2 ! 373: mov [esp].sf_ptlOrg.ptl_x,eax ! 374: ;ptlOrg.x = floor(M0 / F) ! 375: mov [esp].sf_ptlOrg.ptl_y,ebp ! 376: ;ptlOrg.y = floor(N0 / F) ! 377: ! 378: ; Calculate the correct [esp].sf_y1: ! 379: ! 380: lea ebp,[ebx + esi] ;ebp = M1 ! 381: and ebp,F - 1 ! 382: ! 383: if (flags AND ROUND_Y_DOWN) ! 384: cmp ebp,1 ! 385: sbb ebp,8 ;M1 -= 8 ! 386: else ! 387: sub ebp,8 ;M1 -= 8 ! 388: endif ! 389: sbb eax,eax ! 390: xor ebp,eax ! 391: sub ebp,eax ;M1 = ABS(M1) ! 392: ! 393: lea edx,[ecx + edi] ! 394: mov eax,edx ! 395: sar edx,FLOG2 ! 396: and eax,F - 1 ! 397: jz short @f ;special case for N1 == 0 ! 398: cmp eax,ebp ;cmp N1, M1 ! 399: sbb edx,-1 ;edx is now one pixel past the actual ! 400: @@: ; end coordinate (note that it hasn't ! 401: ; been affected by the origin shift) ! 402: and ebx,F - 1 ! 403: mov [esp].sf_y1,edx ! 404: ! 405: ; Calculate our error term for y = 0. ! 406: ; ! 407: ; NOTE: Since this routine is used only for lines that are unclipped, we ! 408: ; are guaranteed by our screen size that the values will be far less ! 409: ; than 32 bits in significance, and so we don't worry about overflow. ! 410: ; If this is used for clipped lines, these multiplies will have to ! 411: ; be converted to give 64 bit results, because we can have 36 bits of ! 412: ; significance! ! 413: ! 414: lea ebp,[ebx + 8] ;ebp = M0 + 8 ! 415: mov eax,edi ! 416: imul eax,ebp ;eax = dN * (M0 + 8) ! 417: mov ebp,esi ! 418: ! 419: ; We have to special case when N0 is 0 -- we know y0 will be zero. ! 420: ; So we jump ahead a bit to a place where 'ecx' is assumed to contain ! 421: ; y0 -- and it just so happens 'ecx' is zero in this case: ! 422: ! 423: and ecx,F - 1 ! 424: jz short @f ! 425: imul ebp,ecx ;ebp = dM * N0 ! 426: sub eax,ebp ! 427: ! 428: ; Calculate the x-coordinate of the first pixel: ! 429: ! 430: if (flags AND ROUND_Y_DOWN) ! 431: cmp ebx,1 ! 432: sbb ebx,8 ;M0 -= 8 ! 433: else ! 434: sub ebx,8 ;M0 -= 8 ! 435: endif ! 436: sbb ebp,ebp ! 437: xor ebx,ebp ! 438: sub ebx,ebp ;M0 = ABS(M0) ! 439: cmp ecx,ebx ! 440: sbb ecx,ecx ! 441: not ecx ;ecx = -y0 ! 442: ! 443: ; Now adjust the error term accordingly: ! 444: ! 445: @@: ! 446: if (flags AND ROUND_X_DOWN) ! 447: dec eax ! 448: endif ! 449: sar eax,FLOG2 ;eax = floor((M0 + 8) dN - N0 dM] / 16) ! 450: ! 451: mov ebx,[esp].sf_ptlOrg.ptl_x ! 452: mov ebp,[esp].sf_ptlOrg.ptl_y ! 453: ! 454: sub ebp,ecx ;ebp = ptlOrg.ptl_y + y0 ! 455: ! 456: and ecx,esi ! 457: add ecx,eax ! 458: sub ecx,edi ;ecx = dM * x0 + initial error - dN ! 459: jl short @f ;if the error term >= 0, we have to ! 460: sub ecx,edi ; add 1 to the x position and subtract ! 461: inc ebx ; dN off again ! 462: @@: ! 463: ! 464: endm ! 465: ! 466: ;---------------------------Public-Routine------------------------------; ! 467: ; vFastLine(ppdev, ppo, prclClip, apfn, flags) ! 468: ; ! 469: ; Draws fast lines. Or at least attempts to. ! 470: ; ! 471: ; Input: ! 472: ; ! 473: ; ppdev - PDEV pointer ! 474: ; ppo - path ! 475: ; prclClip - pointer to rectangle array for passing to 'bLines' ! 476: ; apfn - pointer to strip routines for passing to 'bLines' ! 477: ; flags - status flag for passing to 'bLines' ! 478: ; ! 479: ;-----------------------------------------------------------------------; ! 480: ! 481: ; NOTE: Don't go changing parameters without also changing STACK_FRAME! ! 482: ! 483: cProc vFastLine,20,< \ ! 484: uses esi edi ebx, \ ! 485: ebp_ppdev: ptr, \ ! 486: ebp_ppo: ptr, \ ! 487: ebp_prclClip: ptr, \ ! 488: ebp_apfn: ptr, \ ! 489: ebp_flags: dword > ! 490: ! 491: ; Leave room for our stack frame. ! 492: ; ! 493: ; NOTE: Don't add local variables here -- you can't reference them with ! 494: ; ebp anyway! Add them to the STACK_FRAME structure. ! 495: ! 496: local aj[(size STACK_FRAME) - 4 * (STATE_MEM_SIZE + PROC_MEM_SIZE)]: byte ! 497: ! 498: ; We save 'ebp' on the stack (note that STACK_FRAME accounts for this push): ! 499: ! 500: push ebp ! 501: ! 502: mov [esp].sf_ulLastLength,-1;make sure first line in path resets ! 503: ; LINE_MAX value ! 504: ! 505: ; Now get some path stuff: ! 506: ! 507: next_record: ! 508: ! 509: mov eax,[esp].sf_ppo ! 510: lea ebx,[esp].sf_pd ! 511: cCall PATHOBJ_bEnum,<eax,ebx> ! 512: mov [esp].sf_bMore,eax ;save away return code for later ! 513: ! 514: mov ebx,[esp].sf_pd.pd_count;if 0 points in record, get outta here ! 515: or ebx,ebx ! 516: jz check_for_closefigure ! 517: ! 518: lea ebp,[8 * ebx - 8] ! 519: add ebp,[esp].sf_pd.pd_pptfx ! 520: mov [esp].sf_pptfxEnd,ebp ;points to last point in record ! 521: ! 522: mov ecx,[esp].sf_pd.pd_flags ! 523: test ecx,PD_BEGINSUBPATH ! 524: jz short continue_subpath ! 525: ! 526: ; Handle a new sub-path: ! 527: ! 528: mov eax,[esp].sf_pd.pd_pptfx ! 529: add eax,8 ! 530: mov [esp].sf_pptfx,eax ! 531: ! 532: mov esi,[ebp].ptl_x ;remember last point in case we have ! 533: mov edi,[ebp].ptl_y ; to continue to another record ! 534: mov [esp].sf_ptfxLast.ptl_x,esi ! 535: mov [esp].sf_ptfxLast.ptl_y,edi ! 536: ! 537: mov ebx,[eax - 8].ptl_x ;load up current start and end point ! 538: mov ecx,[eax - 8].ptl_y ! 539: mov esi,[eax].ptl_x ! 540: mov edi,[eax].ptl_y ! 541: mov [esp].sf_ptfxStartFigure.ptl_x,ebx ! 542: mov [esp].sf_ptfxStartFigure.ptl_y,ecx ! 543: ! 544: mov [esp].sf_bSetCP,1 ;this line is first in figure ! 545: ! 546: cmp eax,[esp].sf_pptfxEnd ;we have to be careful when the only ! 547: ; point in the record is the start- ! 548: ; figure point (pretty rare) ! 549: jbe new_line ! 550: jmp short next_record ! 551: ! 552: continue_subpath: ! 553: ! 554: ; This record continues the path: ! 555: ! 556: mov eax,[esp].sf_pd.pd_pptfx ! 557: mov ebx,[esp].sf_ptfxLast.ptl_x ;load up current start point ! 558: mov ecx,[esp].sf_ptfxLast.ptl_y ! 559: ! 560: mov esi,[ebp].ptl_x ;remember last point in case we have ! 561: mov edi,[ebp].ptl_y ; to continue to another record ! 562: mov [esp].sf_ptfxLast.ptl_x,esi ! 563: mov [esp].sf_ptfxLast.ptl_y,edi ! 564: ! 565: mov esi,[eax].ptl_x ;load up current end point ! 566: mov edi,[eax].ptl_y ! 567: mov [esp].sf_pptfx,eax ! 568: ! 569: jmp new_line ! 570: ! 571: ;///////////////////////////////////////////////////////////////////// ! 572: ;// Next Line Stuff ! 573: ;///////////////////////////////////////////////////////////////////// ! 574: ! 575: handle_closefigure: ! 576: mov [esp].sf_pd.pd_flags,0 ! 577: mov ebx,[esp].sf_ptfxLast.ptl_x ! 578: mov ecx,[esp].sf_ptfxLast.ptl_y ! 579: mov esi,[esp].sf_ptfxStartFigure.ptl_x ! 580: mov edi,[esp].sf_ptfxStartFigure.ptl_y ! 581: ! 582: jmp new_line ! 583: ! 584: ; Before getting the next path record, see if we have to do a closefigure: ! 585: ! 586: check_for_closefigure: ! 587: test [esp].sf_pd.pd_flags,PD_CLOSEFIGURE ! 588: jnz handle_closefigure ! 589: mov esi,[esp].sf_bMore ! 590: or esi,esi ! 591: jnz next_record ! 592: ! 593: all_done: ! 594: ! 595: pop ebp ! 596: cRet vFastLine ! 597: ! 598: ;///////////////////////////////////////////////////////////////////// ! 599: ;// Output Integer Line ! 600: ;///////////////////////////////////////////////////////////////////// ! 601: ! 602: ; ebx = x ! 603: ; ecx = y ! 604: ; esi = dx ! 605: ; edi = dy ! 606: ; [esp].sf_ulErrorTerm = incomplete error term (actual value is 'dx - bias') ! 607: ; [esp].sf_ulCmd = draw command ! 608: ! 609: ; NOTE: The port values retrieved from the PDEV are word values, and word ! 610: ; moves have a one cycle penalty. For this reason, the values should ! 611: ; actually be defined as dwords in the PDEV... ! 612: ! 613: public int_output_line ! 614: int_output_line: ! 615: mov ebp,[esp].sf_ppdev ;ebp = ppdev ! 616: cmp [esp].sf_bSetCP,0 ! 617: je short int_current_position_already_set ! 618: ! 619: mov dx,[ebp].pdev_gp_stat ! 620: @@: in ax,dx ! 621: and eax,FIFO_7_EMPTY ;wait for 7 entries ! 622: jnz short @b ! 623: ! 624: mov dx,[ebp].pdev_cur_x ! 625: mov eax,ebx ! 626: out dx,ax ! 627: ! 628: mov dx,[ebp].pdev_cur_y ! 629: mov eax,ecx ! 630: out dx,ax ! 631: ! 632: mov [esp].sf_bSetCP,0 ;the next integer line in this figure ! 633: ; will have the CP set correctly ! 634: ! 635: jmp short int_output_common ! 636: ! 637: int_current_position_already_set: ! 638: mov dx,[ebp].pdev_gp_stat ! 639: @@: in ax,dx ! 640: and eax,FIFO_5_EMPTY ;wait for 5 entries ! 641: jnz short @b ! 642: ! 643: public int_output_common ! 644: int_output_common: ! 645: cmp esi,[esp].sf_ulLastLength ! 646: je short @f ! 647: ! 648: mov dx,[ebp].pdev_line_max ! 649: mov eax,esi ! 650: out dx,ax ! 651: mov [esp].sf_ulLastLength,eax ! 652: @@: ! 653: mov dx,[ebp].pdev_axstp ! 654: mov eax,edi ! 655: out dx,ax ;axial = dy ! 656: ! 657: mov dx,[ebp].pdev_diastp ! 658: sub eax,esi ! 659: out dx,ax ;diag = dy - dx ! 660: ! 661: mov edx,[esp].sf_ulErrorTerm ! 662: sar edx,1 ! 663: add eax,edx ! 664: mov dx,[ebp].pdev_err_term ! 665: out dx,ax ;err = dy - dx + floor((dx - bias) / 2) ! 666: ! 667: mov dx,[ebp].pdev_cmd ! 668: mov eax,[esp].sf_ulCmd ! 669: out dx,ax ;draw that puppy ! 670: ! 671: ;///////////////////////////////////////////////////////////////////// ! 672: ;// Main Loop ! 673: ;///////////////////////////////////////////////////////////////////// ! 674: ! 675: public next_line ! 676: next_line: ! 677: mov eax,[esp].sf_pptfx ! 678: cmp eax,[esp].sf_pptfxEnd ! 679: jae check_for_closefigure ! 680: ! 681: mov ebx,[eax].ptl_x ! 682: mov ecx,[eax].ptl_y ! 683: mov esi,[eax+8].ptl_x ! 684: mov edi,[eax+8].ptl_y ! 685: add eax,8 ! 686: mov [esp].sf_pptfx,eax ! 687: ! 688: public new_line ! 689: new_line: ! 690: ! 691: ; Octants are numbered as follows: ! 692: ; ! 693: ; \ 5 | 6 / ! 694: ; \ | / ! 695: ; 4 \ | / 7 ! 696: ; \ / ! 697: ; -----+----- ! 698: ; /|\ ! 699: ; 3 / | \ 0 ! 700: ; / | \ ! 701: ; / 2 | 1 \ ! 702: ; ! 703: ! 704: ; ebx = M0 ! 705: ; ecx = N0 ! 706: ; esi = M1 (dM) ! 707: ; edi = N1 (dN) ! 708: ! 709: mov [esp].sf_ptfxStart.ptl_x,ebx ! 710: mov [esp].sf_ptfxStart.ptl_y,ecx ! 711: mov [esp].sf_ptfxEnd.ptl_x,esi ! 712: mov [esp].sf_ptfxEnd.ptl_y,edi ! 713: ;save points in case we have to punt ! 714: mov eax,ebx ! 715: or eax,ecx ! 716: or eax,esi ! 717: or eax,edi ! 718: and eax,F-1 ! 719: jnz non_integer ! 720: ! 721: ;///////////////////////////////////////////////////////////////////// ! 722: ;// Integer Lines ! 723: ;///////////////////////////////////////////////////////////////////// ! 724: ! 725: sar ebx,FLOG2 ;x0 ! 726: sar ecx,FLOG2 ;y0 ! 727: sar esi,FLOG2 ;x1 (soon to be dx) ! 728: sar edi,FLOG2 ;y1 (soon to be dy) ! 729: ! 730: sub esi,ebx ! 731: jl int_2_3_4_5 ! 732: jz int_radial_90_270 ! 733: sub edi,ecx ! 734: jl int_6_7 ! 735: jz int_radial_0 ! 736: cmp esi,edi ! 737: jl int_1 ! 738: je int_radial_315 ! 739: ! 740: int_0: ! 741: lea ebp,[esi - 1] ! 742: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X ! 743: mov [esp].sf_ulErrorTerm,ebp ! 744: ! 745: jmp int_output_line ! 746: ! 747: public int_1 ! 748: int_1: ! 749: xchg esi,edi ! 750: lea ebp,[esi - 1] ! 751: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X + MAJOR_Y ! 752: mov [esp].sf_ulErrorTerm,ebp ! 753: ! 754: jmp int_output_line ! 755: ! 756: public int_2_3_4_5 ! 757: int_2_3_4_5: ! 758: neg esi ! 759: sub edi,ecx ! 760: jl int_4_5 ! 761: jz int_radial_180 ! 762: cmp esi,edi ! 763: jl int_2 ! 764: je int_radial_225 ! 765: ! 766: public int_3 ! 767: int_3: ! 768: lea ebp,[esi - 1] ! 769: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y ! 770: mov [esp].sf_ulErrorTerm,ebp ! 771: ! 772: jmp int_output_line ! 773: ! 774: public int_2 ! 775: int_2: ! 776: xchg esi,edi ! 777: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + MAJOR_Y ! 778: mov [esp].sf_ulErrorTerm,esi ! 779: ! 780: jmp int_output_line ! 781: ! 782: public int_4_5 ! 783: int_4_5: ! 784: neg edi ! 785: cmp esi,edi ! 786: jl int_5 ! 787: je int_radial_135 ! 788: ! 789: int_4: ! 790: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD ! 791: mov [esp].sf_ulErrorTerm,esi ! 792: ! 793: jmp int_output_line ! 794: ! 795: public int_5 ! 796: int_5: ! 797: xchg esi,edi ! 798: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y ! 799: mov [esp].sf_ulErrorTerm,esi ! 800: ! 801: jmp int_output_line ! 802: ! 803: public int_6_7 ! 804: int_6_7: ! 805: neg edi ! 806: cmp esi,edi ! 807: jg int_7 ! 808: je int_radial_45 ! 809: ! 810: int_6: ! 811: xchg esi,edi ! 812: lea ebp,[esi - 1] ! 813: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y + PLUS_X ! 814: mov [esp].sf_ulErrorTerm,ebp ! 815: ! 816: jmp int_output_line ! 817: ! 818: public int_7 ! 819: int_7: ! 820: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_X ! 821: mov [esp].sf_ulErrorTerm,esi ! 822: ! 823: jmp int_output_line ! 824: ! 825: ;///////////////////////////////////////////////////////////////////// ! 826: ;// Lines In The 8 Cardinal Directions ! 827: ;///////////////////////////////////////////////////////////////////// ! 828: ! 829: public int_radial_45 ! 830: int_radial_45: ! 831: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 832: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_45 ! 833: jmp short int_output_radial ! 834: ! 835: public int_radial_135 ! 836: int_radial_135: ! 837: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 838: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_135 ! 839: jmp short int_output_radial ! 840: ! 841: public int_radial_225 ! 842: int_radial_225: ! 843: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 844: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_225 ! 845: jmp short int_output_radial ! 846: ! 847: public int_radial_315 ! 848: int_radial_315: ! 849: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 850: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_315 ! 851: jmp short int_output_radial ! 852: ! 853: public int_radial_90_270 ! 854: int_radial_90_270: ! 855: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 856: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_270 ! 857: mov esi,edi ! 858: sub esi,ecx ! 859: jg short int_output_radial ;if top-to-bottom vertical line ! 860: jz next_line ;if zero length line ! 861: ! 862: neg esi ! 863: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 864: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_90 ! 865: jmp short int_output_radial ! 866: ! 867: public int_radial_180 ! 868: int_radial_180: ! 869: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 870: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_180 ! 871: jmp short int_output_radial ! 872: ! 873: int_radial_0: ! 874: mov ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \ ! 875: LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_0 ! 876: ! 877: ; ebx = x ! 878: ; ecx = y ! 879: ; esi = dx (length of radial line since it's normalized) ! 880: ; ebp = drawing command ! 881: ! 882: public int_output_radial ! 883: int_output_radial: ! 884: mov edi,[esp].sf_ppdev ! 885: cmp [esp].sf_bSetCP,0 ! 886: je short int_radial_continue_figure ! 887: ! 888: mov dx,[edi].pdev_gp_stat ! 889: @@: in ax,dx ! 890: and eax,FIFO_4_EMPTY ! 891: jnz short @b ! 892: ! 893: mov dx,[edi].pdev_cur_x ! 894: mov eax,ebx ! 895: out dx,ax ! 896: ! 897: mov dx,[edi].pdev_cur_y ! 898: mov eax,ecx ! 899: out dx,ax ! 900: ! 901: mov [esp].sf_bSetCP,0 ;the next integer line in this figure ! 902: ; will have the CP set correctly ! 903: ! 904: cmp esi,[esp].sf_ulLastLength ! 905: je short @f ! 906: ! 907: mov dx,[edi].pdev_line_max ! 908: mov eax,esi ! 909: out dx,ax ! 910: mov [esp].sf_ulLastLength,eax ! 911: @@: ! 912: mov dx,[edi].pdev_cmd ! 913: mov eax,ebp ! 914: out dx,ax ! 915: jmp next_line ! 916: ! 917: ; Jump to here if we don't have to update the current position first: ! 918: ! 919: public int_radial_continue_figure ! 920: int_radial_continue_figure: ! 921: cmp esi,[esp].sf_ulLastLength ! 922: je short int_radial_skip_length ! 923: ! 924: mov dx,[edi].pdev_gp_stat ! 925: @@: in ax,dx ! 926: and eax,FIFO_2_EMPTY ! 927: jnz short @b ! 928: ! 929: mov dx,[edi].pdev_line_max ! 930: mov eax,esi ! 931: out dx,ax ! 932: mov [esp].sf_ulLastLength,eax ! 933: ! 934: mov dx,[edi].pdev_cmd ! 935: mov eax,ebp ! 936: out dx,ax ! 937: jmp next_line ! 938: ! 939: ; Jump to here if we don't have to update the current position or the ! 940: ; line length variable: ! 941: ! 942: public int_radial_skip_length ! 943: int_radial_skip_length: ! 944: mov dx,[edi].pdev_gp_stat ! 945: @@: in ax,dx ! 946: and eax,FIFO_1_EMPTY ! 947: jnz short @b ! 948: ! 949: mov dx,[edi].pdev_cmd ! 950: mov eax,ebp ! 951: out dx,ax ! 952: jmp next_line ! 953: ! 954: ;///////////////////////////////////////////////////////////////////// ! 955: ;// Non-Integer Lines ! 956: ;///////////////////////////////////////////////////////////////////// ! 957: ! 958: public non_integer ! 959: non_integer: ! 960: sub esi,ebx ! 961: jl non_int_2_3_4_5 ! 962: sub edi,ecx ! 963: jl non_int_6_7 ! 964: cmp esi,edi ! 965: jl non_int_1 ! 966: je non_int_0_slope_one ! 967: ! 968: non_int_0: ! 969: cmp esi,MAX_GIQ_DELTA ! 970: jg punt_line ! 971: ! 972: GIQ ROUND_X_AND_Y_DOWN ! 973: ! 974: non_int_0_common: ! 975: add ecx,edi ;err += dN ! 976: mov [esp].sf_ulErrorTerm,ecx ! 977: ! 978: mov eax,[esp].sf_x1 ! 979: sub eax,ebx ! 980: jle next_line ! 981: mov [esp].sf_cPels,eax ! 982: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X ! 983: ! 984: public non_int_x_major ! 985: non_int_x_major: ! 986: mov ecx,[esp].sf_ppdev ! 987: mov dx,[ecx].pdev_gp_stat ! 988: @@: in ax,dx ! 989: and eax,FIFO_7_EMPTY ;wait for 7 entries ! 990: jnz short @b ! 991: ! 992: ; Fractional end-point lines aren't usually going to have the current ! 993: ; position already set correctly, so we explicitly set the CP each time: ! 994: ! 995: mov dx,[ecx].pdev_cur_x ! 996: mov eax,ebx ! 997: out dx,ax ;x0 ! 998: ! 999: mov dx,[ecx].pdev_cur_y ! 1000: mov eax,ebp ! 1001: out dx,ax ;y0 ! 1002: ! 1003: mov [esp].sf_bSetCP,1 ;the next integer line in this figure ! 1004: ; will not necessarily have the CP set ! 1005: ; correctly ! 1006: ! 1007: mov eax,[esp].sf_cPels ! 1008: cmp eax,[esp].sf_ulLastLength ! 1009: je short @f ! 1010: ! 1011: mov dx,[ecx].pdev_line_max ! 1012: out dx,ax ;length = cPels ! 1013: mov [esp].sf_ulLastLength,eax ! 1014: @@: ! 1015: mov dx,[ecx].pdev_axstp ! 1016: mov eax,edi ! 1017: out dx,ax ;axial = dN ! 1018: ! 1019: mov dx,[ecx].pdev_diastp ! 1020: sub eax,esi ! 1021: out dx,ax ;diag = dN - dM ! 1022: ! 1023: mov dx,[ecx].pdev_err_term ! 1024: mov eax,[esp].sf_ulErrorTerm ! 1025: out dx,ax ;error term ! 1026: ! 1027: mov dx,[ecx].pdev_cmd ! 1028: mov eax,[esp].sf_ulCmd ! 1029: out dx,ax ;output it ! 1030: ! 1031: jmp next_line ! 1032: ! 1033: ; Lines of slope one have a special rounding rule: when the line ! 1034: ; runs exactly half way between two pixels, the upper or right pel ! 1035: ; is illuminated. This translates into x=1/2 rounding up in value, ! 1036: ; and y=1/2 rounding down: ! 1037: ! 1038: public non_int_0_slope_one ! 1039: non_int_0_slope_one: ! 1040: or esi,esi ! 1041: jz next_line ;quick check for a zero length GIQ line ! 1042: ! 1043: cmp esi,MAX_GIQ_DELTA ! 1044: jg punt_line ! 1045: ! 1046: GIQ ROUND_Y_DOWN_SLOPE_ONE ! 1047: jmp non_int_0_common ! 1048: ! 1049: public non_int_1 ! 1050: non_int_1: ! 1051: cmp edi,MAX_GIQ_DELTA ! 1052: jg punt_line ! 1053: ! 1054: GIQR ROUND_X_AND_Y_DOWN ! 1055: add ecx,esi ;err += dM ! 1056: mov [esp].sf_ulErrorTerm,ecx ! 1057: ! 1058: mov eax,[esp].sf_y1 ! 1059: sub eax,ebp ! 1060: jle next_line ! 1061: mov [esp].sf_cPels,eax ! 1062: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X + MAJOR_Y ! 1063: ! 1064: public non_int_y_major ! 1065: non_int_y_major: ! 1066: mov ecx,[esp].sf_ppdev ! 1067: mov dx,[ecx].pdev_gp_stat ! 1068: @@: in ax,dx ! 1069: and eax,FIFO_7_EMPTY ;wait for 7 entries ! 1070: jnz short @b ! 1071: ! 1072: ; Fractional end-point lines aren't usually going to have the current ! 1073: ; position already set correctly, so we explicitly set the CP each time: ! 1074: ! 1075: mov dx,[ecx].pdev_cur_x ! 1076: mov eax,ebx ! 1077: out dx,ax ;x0 ! 1078: ! 1079: mov dx,[ecx].pdev_cur_y ! 1080: mov eax,ebp ! 1081: out dx,ax ;y0 ! 1082: ! 1083: mov [esp].sf_bSetCP,1 ;the next integer line in this figure ! 1084: ; will not necessarily have the CP set ! 1085: ; correctly ! 1086: ! 1087: mov eax,[esp].sf_cPels ! 1088: cmp eax,[esp].sf_ulLastLength ! 1089: je short @f ! 1090: ! 1091: mov dx,[ecx].pdev_line_max ! 1092: out dx,ax ;length = cPels ! 1093: mov [esp].sf_ulLastLength,eax ! 1094: @@: ! 1095: mov dx,[ecx].pdev_axstp ! 1096: mov eax,esi ! 1097: out dx,ax ;axial = dM ! 1098: ! 1099: mov dx,[ecx].pdev_diastp ! 1100: sub eax,edi ! 1101: out dx,ax ;diag = dM - dN ! 1102: ! 1103: mov dx,[ecx].pdev_err_term ! 1104: mov eax,[esp].sf_ulErrorTerm ! 1105: out dx,ax ;error term ! 1106: ! 1107: mov dx,[ecx].pdev_cmd ! 1108: mov eax,[esp].sf_ulCmd ! 1109: out dx,ax ;output it ! 1110: ! 1111: jmp next_line ! 1112: ! 1113: public non_int_2_3_4_5 ! 1114: non_int_2_3_4_5: ! 1115: neg esi ;dM = -dM (now positive) ! 1116: neg ebx ;M0 = -M0 ! 1117: sub edi,ecx ! 1118: jl non_int_4_5 ! 1119: cmp esi,edi ! 1120: jl non_int_2 ! 1121: ! 1122: non_int_3: ! 1123: cmp esi,MAX_GIQ_DELTA ! 1124: jg punt_line ! 1125: ! 1126: GIQ ROUND_Y_DOWN ! 1127: add ecx,edi ;err += dN ! 1128: mov [esp].sf_ulErrorTerm,ecx ! 1129: ! 1130: neg ebx ;untransform x0 ! 1131: ! 1132: mov eax,[esp].sf_x1 ! 1133: add eax,ebx ! 1134: jle next_line ! 1135: mov [esp].sf_cPels,eax ! 1136: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y ! 1137: ! 1138: jmp non_int_x_major ! 1139: ! 1140: public non_int_2 ! 1141: non_int_2: ! 1142: cmp edi,MAX_GIQ_DELTA ! 1143: jg punt_line ! 1144: ! 1145: GIQR ROUND_Y_DOWN ! 1146: add ecx,esi ;err += dM ! 1147: mov [esp].sf_ulErrorTerm,ecx ! 1148: ! 1149: neg ebx ;untransform x0 ! 1150: ! 1151: mov eax,[esp].sf_y1 ! 1152: sub eax,ebp ! 1153: jle next_line ! 1154: mov [esp].sf_cPels,eax ! 1155: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + MAJOR_Y ! 1156: ! 1157: jmp non_int_y_major ! 1158: ! 1159: public non_int_4_5 ! 1160: non_int_4_5: ! 1161: neg edi ;dN = -dN (now positive) ! 1162: neg ecx ;N0 = -N0 ! 1163: cmp esi,edi ! 1164: jl non_int_5 ! 1165: je non_int_4_slope_one ! 1166: ! 1167: public non_int_4 ! 1168: non_int_4: ! 1169: cmp esi,MAX_GIQ_DELTA ! 1170: jg punt_line ! 1171: ! 1172: GIQ 0 ! 1173: ! 1174: non_int_4_common: ! 1175: add ecx,edi ;err += dN ! 1176: mov [esp].sf_ulErrorTerm,ecx ! 1177: ! 1178: neg ebx ;untransform x0 ! 1179: neg ebp ;untransform y0 ! 1180: ! 1181: mov eax,[esp].sf_x1 ! 1182: add eax,ebx ! 1183: jle next_line ! 1184: mov [esp].sf_cPels,eax ! 1185: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD ! 1186: ! 1187: jmp non_int_x_major ! 1188: ! 1189: ; Lines of slope one have a special rounding rule. ! 1190: ! 1191: public non_int_4_slope_one ! 1192: non_int_4_slope_one: ! 1193: cmp esi,MAX_GIQ_DELTA ! 1194: jg punt_line ! 1195: ! 1196: GIQ ROUND_X_DOWN_SLOPE_ONE ! 1197: jmp non_int_4_common ! 1198: ! 1199: public non_int_5 ! 1200: non_int_5: ! 1201: cmp edi,MAX_GIQ_DELTA ! 1202: jg punt_line ! 1203: ! 1204: GIQR 0 ! 1205: add ecx,esi ;err += dM ! 1206: mov [esp].sf_ulErrorTerm,ecx ! 1207: ! 1208: neg ebx ;untransform x0 ! 1209: neg ebp ;untransform y0 ! 1210: ! 1211: mov eax,[esp].sf_y1 ! 1212: add eax,ebp ! 1213: jle next_line ! 1214: mov [esp].sf_cPels,eax ! 1215: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y ! 1216: ! 1217: jmp non_int_y_major ! 1218: ! 1219: public non_int_6_7 ! 1220: non_int_6_7: ! 1221: neg edi ;dN = -dN (now positive) ! 1222: neg ecx ;M0 = -M0 ! 1223: cmp esi,edi ! 1224: je non_int_7_slope_one ! 1225: jg non_int_7 ! 1226: ! 1227: public non_int_6 ! 1228: non_int_6: ! 1229: cmp edi,MAX_GIQ_DELTA ! 1230: jg punt_line ! 1231: ! 1232: GIQR ROUND_X_DOWN ! 1233: add ecx,esi ;err += dM ! 1234: mov [esp].sf_ulErrorTerm,ecx ! 1235: ! 1236: neg ebp ;untransform y0 ! 1237: ! 1238: mov eax,[esp].sf_y1 ! 1239: add eax,ebp ! 1240: jle next_line ! 1241: mov [esp].sf_cPels,eax ! 1242: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y + PLUS_X ! 1243: ! 1244: jmp non_int_y_major ! 1245: ! 1246: public non_int_7 ! 1247: non_int_7: ! 1248: cmp esi,MAX_GIQ_DELTA ! 1249: jg punt_line ! 1250: ! 1251: GIQ ROUND_X_DOWN ! 1252: ! 1253: non_int_7_common: ! 1254: add ecx,edi ;err += dN ! 1255: mov [esp].sf_ulErrorTerm,ecx ! 1256: ! 1257: neg ebp ;untransform y0 ! 1258: ! 1259: mov eax,[esp].sf_x1 ! 1260: sub eax,ebx ! 1261: jle next_line ! 1262: mov [esp].sf_cPels,eax ! 1263: mov [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_X ! 1264: ! 1265: jmp non_int_x_major ! 1266: ! 1267: public non_int_7_slope_one ! 1268: non_int_7_slope_one: ! 1269: cmp esi,MAX_GIQ_DELTA ! 1270: jg punt_line ! 1271: ! 1272: GIQ ROUND_X_DOWN_SLOPE_ONE ! 1273: jmp non_int_7_common ! 1274: ! 1275: ;///////////////////////////////////////////////////////////////////// ! 1276: ;// Punt Line ! 1277: ;///////////////////////////////////////////////////////////////////// ! 1278: ! 1279: ; If the line is too long, we punt to our strip drawing routine. ! 1280: ! 1281: public punt_line ! 1282: punt_line: ! 1283: mov esi,esp ! 1284: lea eax,[esp].sf_ptfxStart ! 1285: lea ebx,[esp].sf_ptfxEnd ! 1286: ! 1287: cCall bLines,<[esi].sf_ppdev, eax, ebx, 0, 1, 0, \ ! 1288: [esi].sf_prclClip, [esi].sf_apfn, [esi].sf_flags> ! 1289: ! 1290: mov [esp].sf_bSetCP,1 ;Always reset CP after punting ! 1291: mov [esp].sf_ulLastLength,-1;Always reset line length after punting ! 1292: ! 1293: jmp next_line ! 1294: ! 1295: endProc vFastLine ! 1296: ! 1297: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.