📄 simple_graphics.c
字号:
/******************************************************************* 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, alt_video_display* display){ 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(display->color_depth == 32) { addr = (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) + ((V * (display->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(display->color_depth == 24) { addr = (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) + ((V * (display->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(display->color_depth == 16) { addr = (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) + ((V * (display->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, alt_video_display* display ){ unsigned short* temp_line; int index_24 = 0; int index_16 = 0; unsigned int dest_addr; unsigned int bytes_in_line; dest_addr = (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) + ((y * (display->width * (display->bytes_per_pixel))) + (x * (display->bytes_per_pixel))); bytes_in_line = num_pixels * display->bytes_per_pixel; if(source_color_depth == 24) { if(display->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(display->color_depth == 24) { memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line ); } } else if(source_color_depth == 16) { if(display->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(display->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, alt_video_display* display){ // 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, display); // 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, display); // 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, alt_video_display* display){ int x = 0; int y = radius; int p = (5 - radius*4)/4; // Start the circle with the top, bottom, left, and right pixels. vid_round_corner_points(Hcenter, Vcenter, x, y, 0, 0, color, fill, display); // 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_round_corner_points(Hcenter, Vcenter, x, y, 0, 0, color, fill, display); } return (0);}/******************************************************************* Function: vid_draw_round_corner_box** Purpose: Draws a box on the screen with the specified corner* points. The fill parameter tells the function whether or not* to fill in the box. 1 = fill, 0 = do not fill.*******************************************************************/int vid_draw_round_corner_box ( int horiz_start, int vert_start, int horiz_end, int vert_end, int radius, int color, int fill, alt_video_display* display){ unsigned int x, y; int p; int diameter; int temp; unsigned int width, height, straight_width, straight_height; // Make sure the start point us up and left of the end point if( horiz_start > horiz_end ) { temp = horiz_end; horiz_end = horiz_start; horiz_start = temp; } if( vert_start > vert_end ) { temp = vert_end; vert_end = vert_start; vert_start = temp; } // These are the overall dimensions of the box width = horiz_end - horiz_start; height = vert_end - vert_start; // Make sure our radius isnt more than the shortest dimension // of the box, or it'll screw us all up if( radius > ( width / 2 )) radius = width / 2; if( radius > ( height / 2 )) radius = height / 2; // We use the diameter for some calculations, so we'll pre calculate it here. diameter = ( radius * 2 ); // These are the lengths of the straight portions of the box edges. straight_width = width - diameter; straight_height = height - diameter; x = 0; y = radius; p = (5 - radius*4)/4; // Start the corners with the top, bottom, left, and right pixels. vid_round_corner_points( horiz_start + radius, vert_start + radius, x, y, straight_width, straight_height, color, fill, display ); // 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_round_corner_points( horiz_start + radius, vert_start + radius, x, y, straight_width, straight_height, color, fill, display); } // If we want to fill in our box if (fill) { vid_paint_block (horiz_start, vert_start + radius, horiz_end, vert_end - radius, color, display); // If we're not filling in the box, just draw four lines. } else { vid_draw_line(horiz_start, vert_start + radius, horiz_start, vert_end - radius , 1, color, display); //left vid_draw_line(horiz_end, vert_start + radius, horiz_end, vert_end - radius , 1, color, display); //right vid_draw_line(horiz_start + radius, vert_start, horiz_end - radius , vert_start, 1, color, display); //top vid_draw_line(horiz_start + radius, vert_end, horiz_end - radius , vert_end, 1, color, display); //bottom } return (0);}/******************************************************************* Function: vid_round_corner_points** Purpose: Called by vid_draw_round_corner_box() and * vid_draw_circle() to plot the actual points of the round corners.* Draws horizontal lines to fill the shape.*******************************************************************/void vid_round_corner_points( int cx, int cy, int x, int y, int straight_width, int straight_height, int color, char fill, alt_video_display* display){ // If we're directly above, below, left and right of center (0 degrees), plot those 4 pixels if (x == 0) { // bottom vid_set_pixel(cx, cy + y + straight_height, color, display); vid_set_pixel(cx + straight_width, cy + y + straight_height, color, display); // top vid_set_pixel(cx, cy - y, color, display); vid_set_pixel(cx + straight_width, cy - y, color, display); if(fill) { vid_draw_line(cx - y, cy, cx + y + straight_width, cy, 1, color, display); vid_draw_line(cx - y, cy + straight_height, cx + y + straight_width, cy + straight_height, 1, color, display); } else { //right vid_set_pixel(cx + y + straight_width, cy, color, display);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -