📄 simple_graphics.c
字号:
/***********************************************************************
* *
* File: simple_graphics.c *
* *
* Purpose: Contains some useful graphics routines *
* *
* Author: N. Knight *
* Altera Corporation *
* Apr 2006 *
**********************************************************************/
#include <string.h>
#include "simple_graphics.h"
#include "io.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, frame_buffer_struct* frame_buffer)
{
if( vert_start == vert_end )
{
// c2h_draw_horiz_line( (unsigned short)horiz_start,
// (unsigned short)horiz_end,
// (unsigned short)vert_start,
// color,
// frame_buffer->frame1);
vid_draw_horiz_line( (unsigned short)horiz_start,
(unsigned short)horiz_end,
(unsigned short)vert_start,
color,
frame_buffer );
}
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,
frame_buffer );
}
}
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, frame_buffer_struct* frame_buffer)
{
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, frame_buffer);
// Otherwise, set it to the background color.
} else {
vid_set_pixel(x_index, scroll->vbegin + char_row, scroll->b_color, frame_buffer); //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, frame_buffer);
// 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, frame_buffer_struct* frame_buffer)
{
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, frame_buffer);
vid_set_pixel(write_x, write_y, temp_pixel, frame_buffer);
if(read_x >= xend + x_distance || read_y >= yend + y_distance)
{
vid_set_pixel(read_x, read_y, backfill_color, frame_buffer);
}
}
}
}
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, frame_buffer_struct* frame_buffer, 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, frame_buffer);
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, frame_buffer_struct* frame_buffer)
{
// If we want to fill in our box
if (fill) {
vid_paint_block (horiz_start, vert_start, horiz_end, vert_end, color, frame_buffer);
// 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, frame_buffer);
vid_draw_line(horiz_end-1, vert_start, horiz_end-1, vert_end-1, 1, color, frame_buffer);
vid_draw_line(horiz_start, vert_start, horiz_end-1, vert_start, 1, color, frame_buffer);
vid_draw_line(horiz_start, vert_end-1, horiz_end-1, vert_end-1, 1, color, frame_buffer);
}
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, frame_buffer_struct* frame_buffer)
{
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, frame_buffer); // 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, frame_buffer_struct* frame_buffer)
{
int addr;
if( frame_buffer->color_depth == 32 )
{
addr = ( ( (int)(frame_buffer->frame1) )+ (vert * (frame_buffer->width * 4)) + horiz * 4);
IOWR_32DIRECT( addr, 0, (unsigned int)(color));
}
else if( frame_buffer->color_depth == 24 )
{
addr = ( ( (int)(frame_buffer->frame1) )+ (vert * (frame_buffer->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( frame_buffer->color_depth == 16 )
{
addr = ( ( (int)(frame_buffer->frame1) )+ (vert * (frame_buffer->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, frame_buffer_struct* frame_buffer)
{
int addr;
addr = ( ( (int)(frame_buffer->frame1) )+ (vert * (frame_buffer->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, frame_buffer_struct* frame_buffer)
{
int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -