Handmade Hero » Forums » Code » DrawRectangle and type-casting
C_Worm
29 posts
#21641 DrawRectangle and type-casting
2 weeks, 6 days ago Edited by C_Worm on Sept. 25, 2019, 7:41 p.m. Reason: Initial post

Why can't we put the type cast out side the loop.

int *Pixel = (int*)Row;

I mean, why do we have to typecast the row pointer every time.

if we only typecast it before the loop, does it only point to (int*) once, and then point to (char*) for the rest of the loop??


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void drawRectangle(BitmapInfo *bmpInfo, int x, int y, int width, int height, int Color)
{
	if(x < 0)
	{
		x = 0;
	}
	if(y < 0)
	{
		y = 0;
	}
	if(width > bmpInfo->width)
	{
		width = bmpInfo->width;
	}
	if(height > bmpInfo->height)
	{
		height = bmpInfo->height;
	}

	int Pitch = bmpInfo->width * 4;

	char *Row = (char*)bmpInfo->memory + (x * 4) + (y * Pitch); 

                                              here? <--------------------------------------------------
                                                                                    
	for(int yi = y; yi < height; yi++)                                       
	{                                                                            
		int *Pixel = (int*)Row;   <-------- why doesn't it work to put this outside the loop?
		for(int xi = x; xi < width; xi++)
		{
			*Pixel++ = Color;
		}

		Row += Pitch;
	}
}
shwa
Joshua
3 posts
#21642 DrawRectangle and type-casting
2 weeks, 6 days ago Edited by Joshua on Sept. 25, 2019, 7:54 p.m.

Line 34 (`Row += Pitch;`) modifies what `Row` is actually pointing to, so Pixel isn't pointing to the same thing every iteration.
C_Worm
29 posts
#21643 DrawRectangle and type-casting
2 weeks, 6 days ago

but Pixel is pointing at whatever Row is pointing to, so modifying Row should also affect Pixel??
mmozeiko
Mārtiņš Možeiko
1974 posts / 1 project
#21644 DrawRectangle and type-casting
2 weeks, 6 days ago Edited by Mārtiņš Možeiko on Sept. 25, 2019, 8:20 p.m.

It does not work, because Pixel++ assumes that next pixel to fill follows in memory directly afterwards. Which is not true if x != 0 or width != bitmap width.

Here's an illustration (4x4 image):
1
2
3
4
ABCD
EFGH
IJKL
MNOP


If you ask to drawRectangle with x=1, y=1, width=1, height=2, then it should fill only F and J values.
Initially you calculate Row to point to F pixel (line 22).
Then you assign Pixel pointer to same value (line 28).
Now in you do Pixel++ so it will point to G (line 31).

In case you do Row += Pitch, it will now go from F to J pixel correctly. Because Row from F pixel + Pitch is J pixel.
But in case you reuse Pixel value in next loop iteration, it will fill G pixel.

To better understand how values change, I strongly recommend you to use debugger. Set up watch window to show values of variables (Row, Pixel, Pitch, x, y, ...) and step line by line over small example (1x2 rectangel) and see how values are changing.
shwa
Joshua
3 posts
#21645 DrawRectangle and type-casting
2 weeks, 6 days ago

but Pixel is pointing at whatever Row is pointing to, so modifying Row should also affect Pixel??


They are pointing at the same thing, but if you change Row then they will no longer be pointing at the same thing.

Let's say we have an array of numbers where both Row and Pixel are pointing to the first element:

1
2
3
Row      v
         0  1  2  3  4  5
Pixel    ^


If we then do `Row += 1;` we get the following:

1
2
3
Row         v
         0  1  2  3  4  5
Pixel    ^
sagian2005
1 posts
This newly registered member has not yet activated their account.
#21648 DrawRectangle and type-casting
2 weeks, 5 days ago

"Row" is a pointer to the first pixel to be filled in each row.
"Pixel" is a pointer to each successive pixel in that row.

Each pixel is set until the _rectangle_ "Width" is reached.
Then the "Row" pointer is incremented by the destination _bitmap_ "Pitch".

The "Row" pointer needs to be incremented by the destination bitmap's "Pitch" in the outer loop so that it points to the first pixel in each row to be filled.

The "Pixel" pointer starts at the beginning of the row to be filled by the inner loop.

One thing to keep in mind is that the width x height of the rectangle we're filling is not the same as the width x height of the destination bitmap. We're filling an arbitrary rectangle with color _within_ the destination bitmap.
debiatan
Miguel Lechón
73 posts
#21649 DrawRectangle and type-casting
2 weeks, 5 days ago

It should also be noted that type-casting a pointer is just a way of telling the compiler how to interpret data located at a specific memory address and has no run-time cost.