The following code is a Method within a custom `bitmap` type, which draws a line of pixels at any angle, pixel by pixel. The code has been cropped t show only one of the drawing modes (replace mode). Clipping is optionally performed. In the program I am testing with, I call the method as follows:
Test1.PixelLine(-50,-50,x*4,y*4,$FFFFFFFF,0,False)
I can apparently set clipping to True or False and I get the same problem.
The problem is, when I compile my test program with Debug On, the program works correctly and the lines are drawn. When I compile with Debug Off, the program only draws the first pixel of the line. (Normally you'd think it'd be the other way around, or that the debugging wouldn't change behavior?!)
So far I can only tell that, with Debug Off, the program flow doesn't seem to get into the `While` loops, failing the test right away.
Does anyone see what might be causing this strange problem? How can I get this to run with debug off?
Method PixelLine(MXpos1:Int,MYpos1:Int,MXpos2:Int,MYPos2:Int,MColor:Int=$FFFFFFFF,MMode:Int=0,MClip:Int=False)
'To draw a diagonal/straight line of pixels on this `Bitmap` from MXpos,MYpos to MXpos2,MYpos2
'in the given `color` MColor (RGBA) or with XXYY value for each pixel
'Uses the Bresenham's line drawing algorithm with integer math only
'Requires that at least one pixel must be drawable and is within the this `Bitmap` object's memory space if clipping is off
'Performs clipping if MClip is True
'Copies differently based on the MMode. 0=Replace
Local MRowBytes:Int=Width 'RowBytes/4 because it's an Int Pointer
Local MBasePointer:Int Ptr=DataBankIntPtr 'Base address of bitmap memory
Local MColorFast:Int=MColor 'Make sure it's in a register for speed
Local MSteep:Int=Abs(MYpos2-MYpos1) > Abs(MXpos2-MXpos1) 'Boolean
If MSteep '=True?
Local MTemp:Int=MXpos1; MXpos1=MYpos1; MYpos1=MTemp 'Swap X1,Y1
MTemp=MXpos2; MXpos2=MYpos2; MYpos2=MTemp 'Swap X2,Y2
EndIf
Local MDeltaX:Int=Abs(MXpos2-MXpos1) 'X Difference
Local MDeltaY:Int=Abs(MYpos2-MYpos1) 'Y Difference
Local MError:Int=0 'Overflow counter
Local MDeltaError:Int=MDeltaY 'Counter adder
Local MX:Int=MXpos1 'Start at X1,Y1
Local MY:Int=MYpos1
Local MXStep:Int
Local MYStep:Int
If MXpos1<MXpos2 Then MXStep=1 Else MXStep=-1 'Direction
If MYpos1<MYpos2 Then MYStep=1 Else MYStep=-1 'Direction
Select MMode 'Redirect flow
Case 1 If (MColorFast & $000000FF) Then MMode=0
Case 2 If (MaskValue<>MColorFast) Then MMode=0
Case 5 If (MaskValue=MColorFast) Then MMode=0
Case 9 If (MColorFast & $000000FF) Then MMode=0
End Select
Local MClipFast:Int=MClip 'For speed
Local MWidthFast:Int=Width 'For speed
Local MHeightFast:Int=Height 'For speed
Local MClipping:Int=False 'For signalling that a line started outside of the bitmap
Select MMode
Case 0 'Replace mode - Copies RGBA/XXYY solidly overwriting all data
If MSteep
If MClipFast
If MY>-1 And MY<MWidthFast And MX>-1 And MX<MHeightFast
(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast 'Replace at Y,X
MClipping=False 'Does the line start outside the bitmap?
Else
MClipping=True 'The line starts outside the bitmap
EndIf
Else
(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast 'Replace at Y,X
EndIf
Else
If MClipFast
If MX>-1 And MX<MWidthFast And MY>-1 And MY<MHeightFast
(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast 'Replace at X,Y
MClipping=False 'Does the line start outside the bitmap?
Else
MClipping=True 'The line starts outside the bitmap
EndIf
Else
(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast 'Replace at X,Y
EndIf
EndIf
If MClipFast
While MX<>MXpos2
MX:+MXStep 'Move in X
MError:+MDeltaError 'Add to counter
If (MError Shl 1)>MDeltaX 'Would it overflow?
MY:+MYStep 'Move in Y
MError=MError-MDeltaX 'Overflow/wrap the counter
EndIf
If MClipping=False
'Inside the bitmap, draw the pixel
If MSteep
If (MY<0) Or (MY>=MWidthFast) Or (MX<0) Or (MX>=MHeightFast) Then Return
(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast 'Replace at Y,X
Else
If (MX<0) Or (MX>=MWidthFast) Or (MY<0) Or (MY>=MHeightFast) Then Return
(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast 'Replace at X,Y
EndIf
Else
'Outside the bitmap, check if it came inside
If MSteep
If (MY>-1) And (MY<MWidthFast) And (MX>-1) And (MX<MHeightFast) Then MClipping=False
Else
If (MX>-1) And (MX<MWidthFast) And (MY>-1) And (MY<MHeightFast) Then MClipping=False
EndIf
EndIf
Wend
Else
While MX<>MXpos2
MX:+MXStep 'Move in X
MError:+MDeltaError 'Add to counter
If (MError Shl 1)>MDeltaX 'Would it overflow?
MY:+MYStep 'Move in Y
MError=MError-MDeltaX 'Overflow/wrap the counter
EndIf
If MSteep
(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast 'Replace at Y,X
Else
(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast 'Replace at X,Y
EndIf
Wend
EndIf
End Select
End Method
(P.S. use the code for whatever you like, it's not the best but it works - usually.)
The Type fields are as follows if you need to know:
Field DataBankPtr:Byte Ptr 'Byte-Pointer to the actual memory reserved in the bank
Field DataBankIntPtr:Int Ptr 'Int-Pointer to the memory in the bank
Field DataBank:TBank 'Pointer to a TBank object to store data
Field Width:Int 'Total width of the bitmap in terms of pixels or units of representation
Field Height:Int 'Total height of the bitmap in terms of pixels or units of representation
Field RowBytes:Int 'How many total bytes of data are allocated in each row of pixels or units (Width*4)
Field TotalBytes:Int 'How many bytes in total does the bitmap data take up
Field FromPixmap:TPixmap 'Pointer to a Pixmap object which may have been used for loading data from an image, used as a static bank
Field MaskValue:Int 'RGBA color or 4-byte value, where all pixels in the Bitmap of that color/value are transparent/non-copied when copying in Mode 2 (ValueMask mode)
|