📄 simple_graphics.c
字号:
int addr;
int bytes_per_line, bytes_per_pixel;
char* line;
bytes_per_pixel = (frame_buffer->color_depth / 8);
bytes_per_line = ((Hend - Hstart) * bytes_per_pixel);
line = malloc(bytes_per_line + 12);
if(frame_buffer->color_depth == 16)
{
for (i = 0; i < bytes_per_line; i+=2)
{
*(line + i) = (unsigned char)color;
*(line + i + 1) = (unsigned char)(color >> 8);
}
}
else if(frame_buffer->color_depth == 24)
{
for (i = 0; i < bytes_per_line; i+=3)
{
*(line + i) = (unsigned char)color;
*(line + i + 1) = (unsigned char)(color >> 8);
*(line + i + 2) = (unsigned char)(color >> 16);
}
}
else if(frame_buffer->color_depth == 32)
{
for (i = 0; i < bytes_per_line; i+=4)
{
// Does the right hand side of this assignment determine the size?
*(int*)(line + i) = (unsigned int)color;
}
}
/* Initial Address */
addr = (int)(frame_buffer->frame1) + ((Vstart * (frame_buffer->width * bytes_per_pixel)) + (Hstart * bytes_per_pixel));
for (i = Vstart; i < Vend; i++)
{
memcpy( (void*)addr, line, bytes_per_line );
addr += (frame_buffer->width * bytes_per_pixel);
}
free (line);
}
/******************************************************************
* Function: vid_draw_horiz_line
*
* Purpose: Draws a horizontal line on the screen quickly.
* Good for filling stuff.
*
******************************************************************/
void vid_draw_horiz_line (short Hstart, short Hend, int V, int color, frame_buffer_struct* frame_buffer)
{
int i;
int addr;
int bytes_per_line;
char *fast_buffer = malloc(1024 * 3);
if( Hstart > Hend )
{
short temp = Hstart;
Hstart = Hend;
Hend = temp;
}
if(frame_buffer->color_depth == 32)
{
addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 4)) + (Hstart * 4));
bytes_per_line = ((Hend - Hstart) * 4);
for (i = 0; i < bytes_per_line; i+=4)
{
// Does the right hand side of this assignment determine the size?
*(int*)(fast_buffer + i) = (unsigned int)color;
}
memcpy( (void*)addr, fast_buffer, bytes_per_line );
}
if(frame_buffer->color_depth == 24)
{
addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 3)) + (Hstart * 3));
bytes_per_line = ((Hend - Hstart) * 3);
for (i = 0; i < bytes_per_line; i+=3)
{
*(fast_buffer + i) = (unsigned char)color;
*(fast_buffer + i + 1) = (unsigned char)(color >> 8);
*(fast_buffer + i + 2) = (unsigned char)(color >> 16);
}
memcpy( (void*)addr, fast_buffer, bytes_per_line );
}
else if(frame_buffer->color_depth == 16)
{
addr = (int)(frame_buffer->frame1) + ((V * (frame_buffer->width * 2)) + (Hstart * 2));
bytes_per_line = ((Hend - Hstart) * 2);
for (i = 0; i < bytes_per_line; i+=2)
{
*(fast_buffer + i) = (unsigned char)color;
*(fast_buffer + i + 1) = (unsigned char)(color >> 8);
}
memcpy( (void*)addr, fast_buffer, bytes_per_line );
}
free(fast_buffer);
}
/******************************************************************
* Function: vid_merge_colors
*
* Purpose: Takes 5-bit color values for each red, green, and blue
* and merges them into one 16-bit color value.
*
******************************************************************/
int vid_merge_colors(int red, int green, int blue)
{
// Green actually has 6-bits, but we'll make it's LSB 1 to be consistent.
return ((blue) | (((green << 1) | 0x1) << 5) | (red << 11));
}
/******************************************************************
* Function: vid_color_convert24_16
*
* Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color
* sample and converts it to 16-bits, displayable by the
* VGA controller in 16-bit mode
*
******************************************************************/
unsigned short vid_color_convert24_16(char* color24)
{
unsigned char red, green, blue;
unsigned short output;
red = *(color24 + 0) & 0xF8;
green = *(color24 + 1) & 0xFC; // green is actualy 6 bits
blue = *(color24 + 2) & 0xF8;
output = ((blue >> 3) | (green << 3) | (red << 8));
return output;
}
/******************************************************************
* Function: vid_color_convert24_16
*
* Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color
* sample and converts it to 16-bits, displayable by the
* VGA controller in 16-bit mode
*
******************************************************************/
int vid_color_convert16_24(unsigned short color16, char* color24)
{
*(color24 + 0) = color16 >> 11;
*(color24 + 1) = ((color16 & 0x3E) >> 5);
*(color24 + 2) = (color16 & 0x1F);
return (0);
}
/******************************************************************
* Function: vid_copy_line_to_frame_buffer
*
* Purpose: Copies a scanline from memory to the frame buffer at
* the specified coordinates. Converts color depth if
* necessary.
*
******************************************************************/
int vid_copy_line_to_frame_buffer( int x, int y, char* buffer, int num_pixels, int source_color_depth, frame_buffer_struct* frame_buffer )
{
unsigned short* temp_line;
int index_24 = 0;
int index_16 = 0;
unsigned int dest_addr;
unsigned int bytes_in_line;
dest_addr = (int)(frame_buffer->frame1) +
((y * (frame_buffer->width * (frame_buffer->bytes_per_pixel))) +
(x * (frame_buffer->bytes_per_pixel)));
bytes_in_line = num_pixels * frame_buffer->bytes_per_pixel;
if(source_color_depth == 24)
{
if(frame_buffer->color_depth == 16)
{
temp_line = malloc(bytes_in_line);
while(index_24 < bytes_in_line)
{
*(temp_line + index_16) = vid_color_convert24_16_m((char*)(buffer + index_24));
index_16++;
index_24+=3;
}
memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
free(temp_line);
}
else if(frame_buffer->color_depth == 24)
{
memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
}
}
else if(source_color_depth == 16)
{
if(frame_buffer->color_depth == 24)
{
temp_line = malloc(bytes_in_line);
while(index_16 < num_pixels )
{
vid_color_convert16_24((short)*(buffer + index_16), (char*)(temp_line + index_24));
index_16++;
index_24+=3;
}
memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
free(temp_line);
}
else if(frame_buffer->color_depth == 16)
{
memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
}
}
return(0);
}
/******************************************************************
* Function: vid_draw_sloped_line
*
* Purpose: Draws a line between two end points using
* Bresenham's line drawing algorithm.
* width parameter is not used.
* It is reserved for future use.
*
******************************************************************/
void vid_draw_sloped_line( unsigned short horiz_start,
unsigned short vert_start,
unsigned short horiz_end,
unsigned short vert_end,
unsigned short width,
int color,
frame_buffer_struct* frame_buffer)
{
// Find the vertical and horizontal distance between the two points
int horiz_delta = abs(horiz_end-horiz_start);
int vert_delta = abs(vert_end-vert_start);
// Find out what direction we are going
int horiz_incr, vert_incr;
if (horiz_start > horiz_end) { horiz_incr=-1; } else { horiz_incr=1; }
if (vert_start > vert_end) { vert_incr=-1; } else { vert_incr=1; }
// Find out which axis is always incremented when drawing the line
// If it's the horizontal axis
if (horiz_delta >= vert_delta) {
int dPr = vert_delta<<1;
int dPru = dPr - (horiz_delta<<1);
int P = dPr - horiz_delta;
// Process the line, one horizontal point at at time
for (; horiz_delta >= 0; horiz_delta--) {
// plot the pixel
vid_set_pixel(horiz_start, vert_start, color, frame_buffer);
// If we're moving both up and right
if (P > 0) {
horiz_start+=horiz_incr;
vert_start+=vert_incr;
P+=dPru;
} else {
horiz_start+=horiz_incr;
P+=dPr;
}
}
// If it's the vertical axis
} else {
int dPr = horiz_delta<<1;
int dPru = dPr - (vert_delta<<1);
int P = dPr - vert_delta;
// Process the line, one vertical point at at time
for (; vert_delta>=0; vert_delta--) {
// plot the pixel
vid_set_pixel(horiz_start, vert_start, color, frame_buffer);
// If we're moving both up and right
if (P > 0) {
horiz_start+=horiz_incr;
vert_start+=vert_incr;
P+=dPru;
} else {
vert_start+=vert_incr;
P+=dPr;
}
}
}
}
/******************************************************************
* Function: vid_draw_circle
*
* Purpose: Draws a circle on the screen with the specified center
* and radius. Draws symetric circles only. The fill parameter
* tells the function whether or not to fill in the box. 1 = fill,
* 0 = do not fill.
*
******************************************************************/
int vid_draw_circle(int Hcenter, int Vcenter, int radius, int color, char fill, frame_buffer_struct* frame_buffer)
{
int x = 0;
int y = radius;
int p = (5 - radius*4)/4;
// Start the circle with the top, bottom, left, and right pixels.
vid_circle_points(Hcenter, Vcenter, x, y, color, fill, frame_buffer);
// Now start moving out from those points until the lines meet
while (x < y) {
x++;
if (p < 0) {
p += 2*x+1;
} else {
y--;
p += 2*(x-y)+1;
}
vid_circle_points(Hcenter, Vcenter, x, y, color, fill, frame_buffer);
}
return (0);
}
/******************************************************************
* Function: vid_circle_points
*
* Purpose: Called by vid_draw_circle() to plot the actual points
* of the circle. Draws horizontal lines to fill.
*
******************************************************************/
void vid_circle_points(int cx, int cy, int x, int y, int color, char fill, frame_buffer_struct* frame_buffer)
{
// If we're directly above, below, left and right of center (0 degrees), plot those 4 pixels
if (x == 0) {
vid_set_pixel(cx, cy + y, color, frame_buffer);
vid_set_pixel(cx, cy - y, color, frame_buffer);
if(fill) {
vid_draw_line(cx - y, cy, cx + y, cy, 1, color, frame_buffer);
} else {
vid_set_pixel(cx + y, cy, color, frame_buffer);
vid_set_pixel(cx - y, cy, color, frame_buffer);
}
} else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -