📄 simple_graphics.c
字号:
/*********************************************************************** * * * File: simple_graphics.c * * * * Purpose: Contains some useful graphics routines * * * * Author: N. Knight * * Altera Corporation * * Apr 2006 * **********************************************************************/#include <string.h>#include <io.h>#include "alt_video_display.h"#include "simple_graphics.h"#include "sys/alt_alarm.h"#include "sys/alt_cache.h"#include "system.h"/******************************************************************* Function: vid_draw_line** Purpose: Draws a line between two end points. First checks* to see if the line is horizontal. If it is, it calls* vid_draw_horiz_line(), which is much faster than * vid_draw_sloped_line.*******************************************************************/__inline__ void vid_draw_line(int horiz_start, int vert_start, int horiz_end, int vert_end, int width, int color, alt_video_display* display){ if( vert_start == vert_end ) {// c2h_draw_horiz_line( (unsigned short)horiz_start, // (unsigned short)horiz_end, // (unsigned short)vert_start,// color,// display->buffer_ptrs[display->buffer_being_written]->buffer); vid_draw_horiz_line( (unsigned short)horiz_start, (unsigned short)horiz_end, (unsigned short)vert_start, color, display ); } else { vid_draw_sloped_line( (unsigned short)horiz_start, (unsigned short)vert_start, (unsigned short)horiz_end, (unsigned short)vert_end, (unsigned short)width, color, display ); }}void vid_scroll_string_quit(vid_text_scroll_struct* scroll){ free(scroll->string); free(scroll);}vid_text_scroll_struct* vid_scroll_string_init(int hbegin, int vbegin, int hend, int f_color, int b_color, char* font, int ms_delay, char *string){ vid_text_scroll_struct* scroll; scroll = malloc(sizeof (vid_text_scroll_struct)); scroll->hbegin = hbegin; scroll->vbegin = vbegin; scroll->hend = hend; scroll->f_color = f_color; scroll->b_color = b_color; scroll->string = malloc(strlen(string)+2); strcpy(scroll->string, string); scroll->font = font; scroll->ms_delay = ms_delay; scroll->ticks_at_last_move = alt_nticks(); scroll->text_scroll_index = 0; scroll->text_scroll_started = 0; scroll->window_width = scroll->hend - scroll->hbegin; scroll->length_of_string = strlen(string); scroll->string_points = scroll->length_of_string * 8; scroll->scroll_points = (scroll->window_width + scroll->string_points); return(scroll); }int vid_scroll_string(vid_text_scroll_struct* scroll, alt_video_display* display){ int x_start, x_end, x_index, string_x_index, string_char_index, char_row, char_column; char character, column_mask; char* font_char_ptr; char pixels_to_move_by = 1; // If it's time to move the scroll.. if (alt_nticks() >= (scroll->ticks_at_last_move + ((alt_ticks_per_second() * (scroll->ms_delay)) / 1000))) { scroll->ticks_at_last_move = alt_nticks(); // Track where we are in the scroll. if(scroll->text_scroll_started == 0) { scroll->text_scroll_index = 0; scroll->text_scroll_started = 1; } else if(scroll->text_scroll_index >= scroll->scroll_points) { scroll->text_scroll_started = 0; } else { scroll->text_scroll_index += pixels_to_move_by; } //Find out where we start if (scroll->text_scroll_index < scroll->window_width) { x_start = scroll->hbegin + scroll->window_width - scroll->text_scroll_index; } else { x_start = scroll->hbegin; } //Find out where we end if (scroll->string_points > scroll->text_scroll_index) { x_end = scroll->hend; } else { x_end = (scroll->hend - scroll->text_scroll_index + scroll->string_points); } // Write the string segment a column (x) at a time for(x_index = x_start; x_index < x_end; x_index++) { // Find the x index we're at within the string // If first part of string hasnt yet reached left side of scroll window if (scroll->text_scroll_index < scroll->window_width) { string_x_index = (x_index - x_start); } else { string_x_index = scroll->text_scroll_index - scroll->window_width + x_index - x_start; } //Find the character we're supposed to be writing string_char_index = (string_x_index / 8); character = scroll->string[string_char_index]; char_column = (string_x_index % 8); column_mask = (((unsigned int)0x80) >> char_column); font_char_ptr = (scroll->font + ((character - 0x20) * FONT_10PT_ROW)); //We have all the data now, so let's write a column for(char_row = 0; char_row < 11; char_row++) { // If the font table says this pixel is on, then set it to the foreground color if (*(font_char_ptr + char_row) & column_mask) { vid_set_pixel(x_index, scroll->vbegin + char_row, scroll->f_color, display); // Otherwise, set it to the background color. } else { vid_set_pixel(x_index, scroll->vbegin + char_row, scroll->b_color, display); //background color } } } // Erase the leftover column (x) of the last string we wrote. vid_draw_line(x_end, scroll->vbegin, x_end, scroll->vbegin + 10, 1, scroll->b_color, display); // Log what time we moved the scroll. } return(0);}/******************************************************************* Function: vid_move_block** Purpose: Moves a block around the screen, backfilling with * the backfill_color parameter.*******************************************************************/int vid_move_block(int xbegin, int ybegin, int xend, int yend, int x_distance, int y_distance, int backfill_color, alt_video_display* display){ int read_x, read_y, write_x, write_y; short temp_pixel; if(x_distance <= 0 && y_distance <= 0) { //Move by rows because they are contiguous in memory (could help speed if in SDRAM) for (read_y = ybegin; read_y < yend; read_y++) { write_y = read_y + y_distance; for(read_x = xbegin; read_x < xend; read_x++) { write_x = read_x + x_distance; temp_pixel = vid_get_pixel(read_x, read_y, display); vid_set_pixel(write_x, write_y, temp_pixel, display); if(read_x >= xend + x_distance || read_y >= yend + y_distance) { vid_set_pixel(read_x, read_y, backfill_color, display); } } } } return (0);}/******************************************************************* Function: vid_print_string** Purpose: Prints a string to the specified location of the screen* using the specified font and color.* Calls vid_print_char*******************************************************************/int vid_print_string(int horiz_offset, int vert_offset, int color, char *font, alt_video_display* display, char string[]){ int i = 0; int original_horiz_offset; original_horiz_offset = horiz_offset; // Print until we hit the '\0' char. while (string[i]) { //Handle newline char here. if (string[i] == '\n') { horiz_offset = original_horiz_offset; vert_offset += 12; i++; continue; } // Lay down that character and increment our offsets. vid_print_char (horiz_offset, vert_offset, color, string[i], font, display); i++; horiz_offset += 8; } return (0);}/******************************************************************* Function: vid_draw_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_box (int horiz_start, int vert_start, int horiz_end, int vert_end, int color, int fill, alt_video_display* display){ // If we want to fill in our box if (fill) { vid_paint_block (horiz_start, vert_start, horiz_end, vert_end, color, display); // If we're not filling in the box, just draw four lines. } else { vid_draw_line(horiz_start, vert_start, horiz_start, vert_end-1, 1, color, display); vid_draw_line(horiz_end-1, vert_start, horiz_end-1, vert_end-1, 1, color, display); vid_draw_line(horiz_start, vert_start, horiz_end-1, vert_start, 1, color, display); vid_draw_line(horiz_start, vert_end-1, horiz_end-1, vert_end-1, 1, color, display); } return (0);}/******************************************************************* Function: vid_print_char** Purpose: Prints a character to the specified location of the* screen using the specified font and color.*******************************************************************/int vid_print_char (int horiz_offset, int vert_offset, int color, char character, char *font, alt_video_display* display){ int i, j; char temp_char, char_row; // Convert the ASCII value to an array offset temp_char = (character - 0x20); //Each character is 8 pixels wide and 11 tall. for(i = 0; i < 11; i++) { char_row = *(font + (temp_char * FONT_10PT_ROW) + i); for (j = 0; j < 8; j++) { //If the font table says the pixel in this location is on for this character, then set it. if (char_row & (((unsigned char)0x80) >> j)) { vid_set_pixel((horiz_offset + j), (vert_offset + i), color, display); // plot the pixel } } } return(0);}/******************************************************************* Function: vid_set_pixel** Purpose: Sets the specified pixel to the specified color.* Sets one pixel although frame buffer consists of* two-pixel words. Therefore this function is not* efficient when painting large areas of the screen.*******************************************************************/void vid_set_pixel(int horiz, int vert, unsigned int color, alt_video_display* display){ int addr; if( display->color_depth == 32 ) {// addr = ( ( (int)(display->buffer_ptrs[display->buffer_being_written]) )+ (vert * (display->width * 4)) + horiz * 4); addr = ( ( (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) )+ (vert * (display->width * 4)) + horiz * 4); IOWR_32DIRECT( addr, 0, (unsigned int)(color)); } else if( display->color_depth == 24 ) { addr = ( ( (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) )+ (vert * (display->width * 3)) + horiz * 3); IOWR_8DIRECT( addr, 0, (unsigned char)(color)); IOWR_8DIRECT( addr+1, 0, (unsigned char)(color >> 8)); IOWR_8DIRECT( addr+2, 0, (unsigned char)(color >> 16)); } else if( display->color_depth == 16 ) { addr = ( ( (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) )+ (vert * (display->width * 2)) + horiz * 2); IOWR_16DIRECT( addr, 0, (int)(color)); }}/******************************************************************* Function: vid_get_pixel** Purpose: Reads the color of the pixel at the given coordinates*******************************************************************/short vid_get_pixel(int horiz, int vert, alt_video_display* display){ int addr; addr = ( ( (int)(display->buffer_ptrs[display->buffer_being_written]->buffer) )+ (vert * (display->width * 2)) + horiz * 2); return(IORD_16DIRECT(addr, 0));}/******************************************************************* Function: vid_paint_block** Purpose: Paints a block of the screen the specified color.* Note: works with two pixels at a time to maintain high* bandwidth. Therefore, corner points must be even* numbered coordinates. Use vid_draw_solid_box() for* areas with odd-numbered corner points.* The color parameter must contain two pixel's worth* (32 bits).*******************************************************************/void vid_paint_block (int Hstart,int Vstart, int Hend, int Vend, int color, alt_video_display* display){ int i; int addr; int bytes_per_line, bytes_per_pixel; char* line; bytes_per_pixel = (display->color_depth / 8); bytes_per_line = ((Hend - Hstart) * bytes_per_pixel); line = malloc(bytes_per_line + 12); if(display->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(display->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(display->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)(display->buffer_ptrs[display->buffer_being_written]->buffer) + ((Vstart * (display->width * bytes_per_pixel)) + (Hstart * bytes_per_pixel)); for (i = Vstart; i < Vend; i++) { memcpy( (void*)addr, line, bytes_per_line ); addr += (display->width * bytes_per_pixel); } free (line);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -