⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libfbx-line.c

📁 libfxb是linux下只写操作framebuffer的一个轻量级的库。
💻 C
字号:
/* *  libfbx-line.c -- Line Drawing Functions *  (C)opyright 2000-2001 U4X Labs * *  Written by: Mike Bourgeous <nitrogen@u4x.org> *              Sat Sep 2 17:36:28 EDT 2000 * *  $Id: libfbx-line.c,v 1.11 2001/02/04 20:29:56 lethal Exp $ * *       Originally part of fbgraph.c, now separate.  Responsible for *  drawing lines onto surfaces. * *  See ChangeLog for modifications, CREDITS for credits. *  			 *  All source herein is copyright U4X Labs and its original author.  *  Any code modifications or additions are (C)opyright the original  *  author and U4X Labs respectively. * *  libfbx is free software; you can redistribute it and/or modify it  *  under the terms of the GNU Lesser General Public License as  *  published by the Free Software Foundation; either version 2.1 of  *  the License, or (at your option) any later version. * *  libfbx is distributed in the hope that it will be useful, but  *  WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  *  GNU Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with libfbx; if not, write to the Free Software  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *  USA */#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <signal.h>#include <time.h>#include <math.h>#include <linux/fb.h>#include <linux/kd.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/user.h>#include <termios.h>#include <ctype.h>#include <libfbx/libfbx.h>#include <libfbx/libfbx-drivers.h>/* * Function:	draw_horizontal_run() * Arguments:	(*x, *y): Pointers to current coordinates in line,  * 		(run_length): the length of the current run, * 		(x_advance): the size in bytes of one pixel, * 		(r, g, b): the color of the run, * 		(*surface): the destination drawing surface. * Returns:	None * Description:	Helper function for fb_line used to draw horizontal * 		segments in x-major oblique lines, as part of the * 		Bresenham line drawing algorithm.  Never used * 		outside of fb_line, so don't try; the function is * 		useless in any other context. */static void draw_horizontal_run(int *x, int *y, int run_length,                                 int x_advance, int r, int g, int b, 				fb_surface *surface){	int i;	if (run_length < 0)		run_length *= -1;	for (i = 0; i < run_length; i ++)		fb_putpixel(*x + (i * x_advance), 			    *y, r, g, b, surface);	*x += run_length * x_advance;	*y += 1;}/* * Function:	draw_vertical_run() * Arguments:	(*x, *y): Pointers to current coordinates in line,  * 		(run_length): the length of the current run, * 		(x_advance): the size in bytes of one pixel, * 		(r, g, b): the color of the run, * 		(*surface): the destination drawing surface. * Returns:	None * Description: Helper function for fb_line used to draw vertical * 		segments in y-major oblique lines, as part of the * 		Bresenham line drawing algorithm.  Never used * 		outside of fb_line, so don't try; the function is * 		useless in any other context. */static void draw_vertical_run(int *x, int *y, int run_length, 			      int x_advance, int r, int g, int b, 			      fb_surface *surface){	int i;	if (run_length < 0)		run_length *= -1;	for (i = 0; i < run_length; i++)		fb_putpixel(*x, *y + i, 			    r, g, b, 			    surface);	*x += x_advance;	*y += run_length;}/* * Function:	fb_line() * Arguments:	(x1, y1): Coordinates of first point on the line, * 		(x2, y2): Coordinates of last point on the line, * 		(r, g, b): Color of the line, * 		(*surface): Destination drawing surface. * Returns:	None * Description:	Draws a line of the specified color from the specified * 		start point to the specified end point on the specified * 		drawing surface.  One day there may be a function which * 		will allow lines to blend between colors from one point * 		to the other.  fb_line uses Bresenham's run-sliced line  * 		drawing algorithm, based on the implementation by Michael * 		Abrash, and as such is quite fast. */void fb_line(int x1, int y1, 	     int x2, int y2, 	     int r, int g, int b, 	     fb_surface *surface){	int temp, adj_up, adj_down, error_term, 	    x_advance, x_delta, y_delta, whole_step, 	    initial_pixel_count, final_pixel_count, 	    i, run_length;	if (surface->driver != NULL && surface->driver->ops->has_line) {		surface->driver->ops->line(x1, y1, x2, y2, r, g, b, surface);		return;	}	/* 	 * We'll always draw top to bottom, to reduce the number 	 * of cases we have to handle, and to make lines between 	 * the same endpoints draw the same pixels.	 */	if (y1 > y2) {		temp = y1;		y1 = y2;		y2 = temp;		temp = x1;		x1 = x2;		x2 = temp;	}	/* 	 * Figure out whether we're going left or right, and how far 	 * we're going horizontally.	 */	if ((x_delta = x2 - x1) < 0) {		x_advance = -1;		x_delta = -x_delta;	} else {		x_advance = 1;	}	/* Figure out how far we're going vertically */	y_delta = y2 - y1;	/* 	 * Special-case horizontal, vertical, and diagonal lines, 	 * for speed and to avoid nasty boundary conditions and 	 * division by 0.	 */	if (x_delta == 0) {		/* Vertical line */		for (i = 0; i <= y_delta; i++)			fb_putpixel(x1, y1 + i, r, g, b, surface);		return;	}	if (y_delta == 0) {		/* Horizontal line */		if (x_advance < 0) {			for (i = x_delta; i >= 0; 			                  i += x_advance)				fb_putpixel(x1 - i, y1, 					    r, g, b, 					    surface);		} else {			for (i = 0; i <= x_delta; 			            i += x_advance)				fb_putpixel(i + x1, y1, 					    r, g, b, 					    surface);		}		return;	}	if (x_delta == y_delta) {		/* Diagonal line */		for (i = 0; i <= x_delta; i++)			fb_putpixel(x1 + (i * x_advance), 				    y1 + i, r, g, b, surface);		return;	}	/* Determine whether the line is X or Y major, and handle accordingly */	if (x_delta >= y_delta) {		/* X major line */		/* Minimum # of pixels in a run in this line */		whole_step = x_delta / y_delta;		/* 		 * Error term adjust each time Y steps by 1; used to tell 		 * when one extra pixel should be drawn as part of a run, 		 * to account for fractional steps along the X axis per 		 * 1-pixel steps along y		 */		adj_up = (x_delta % y_delta) * 2;		/* 		 * Error term adjust when the error term turns over, used 		 * to factor out the X step made at that time		 */		adj_down = y_delta * 2;		/* 		 * Initial error term; reflects an inital step of 0.5 along 		 * the Y axis		 */		error_term = (x_delta % y_delta) - (y_delta * 2);		/* 		 * The initial and last runs are partial, because Y advances 		 * only 0.5 for these runs, rather than 1.  Divide one full 		 * run, plus the initial pixel, between the initial and last 		 * runs		 */		initial_pixel_count = (whole_step / 2) + 1;		final_pixel_count = initial_pixel_count;		/* 		 * If the basic run length is even and there's no fractional 		 * advance, we have one pixel that could go to either the 		 * inital or last partial run, which we'll arbitrarily allocate		 * to the last run		 */		if ((adj_up == 0) && ((whole_step & 0x01) == 0))			initial_pixel_count--;				/* 		 * If there're an odd number of pixels per run, we have 1 pixel		 * that can't be allocated to either the initial or last 		 * partial run, so we'll add 0.5 to error term so this pixel 		 * will be handled by the normal full-run loop		 */		if ((whole_step & 0x01) != 0)			error_term += y_delta;		/* Draw the first, partial run of pixels */		draw_horizontal_run(&x1, &y1, initial_pixel_count, 				    x_advance, r, g, b, surface);		/* Draw all full runs */		for (i = 0; i < (y_delta - 1); i++) {			/* run is at least this long */			run_length = whole_step;			/* 			 * Advance the error term and add an extra pixel if 			 * the error term so indicates			 */			if ((error_term += adj_up) > 0) {				run_length++;				/* reset the error term */				error_term -= adj_down;			}			/* Draw this scan line's run */			draw_horizontal_run(&x1, &y1, run_length, 				            x_advance, r, g, b, 					    surface);		}		/* Draw the final run of pixels */		draw_horizontal_run(&x1, &y1, final_pixel_count, 				    x_advance, r, g, b, surface);		return;	} else {		/* Y major line */		/* Minimum # of pixels in a run in this line */		whole_step = y_delta / x_delta;		/* 		 * Error term adjust each time X steps by 1; used to tell when 		 * 1 extra pixel should be drawn as part of a run, to account 		 * for fractional steps along the Y axis per 1-pixel steps 		 * along X		 */		adj_up = (y_delta % x_delta) * 2;		/* 		 * Error term adjust when the error term turns over, used to 		 * factor out the Y step made at that time		 */		adj_down = x_delta * 2;		/* Initial error term; reflects initial step of 0.5 along the 		 * X axis 		 */		error_term = (y_delta % x_delta) - (x_delta * 2);		/* 		 * The initial and last runs are partial, because X advances 		 * only 0.5 for these runs, rather than 1.  Divide one full 		 * run, plus the initial pixel, between the initial and last 		 * runs		 */		initial_pixel_count = (whole_step / 2) + 1;		final_pixel_count = initial_pixel_count;		/* 		 * If the basic run length is even and there's no fractional 		 * advance, we have 1 pixel that could go to either the 		 * initial or last partial run, which we'll arbitrarily 		 * allocate to the last run		 */		if ((adj_up == 0) && ((whole_step & 0x01) == 0))			initial_pixel_count--;		/* 		 * If there are an odd number of pixels per run, we have one 		 * pixel that can't be allocated to either the initial or last 		 * partial run, so we'll ad 0.5 to the error term so this 		 * pixel will be handled by the normal rull-run loop		 */		if ((whole_step & 0x01) != 0)			error_term += x_delta;		/* Draw the first, partial run of pixels */		draw_vertical_run(&x1, &y1, initial_pixel_count, 				  x_advance, r, g, b, surface);		/* Draw all full runs */		for (i = 0; i < (x_delta - 1); i++) {			/* run is at least this long */			run_length = whole_step;			/* 			 * Advance the error term and add an extra pixel if the			 * error term so indicates			 */			if ((error_term += adj_up) > 0) {				run_length++;				/* reset the error term */				error_term -= adj_down;			}			/* Draw this scan line's run */			draw_vertical_run(&x1, &y1, run_length, 					  x_advance, r, g, b, 					  surface);		}				/* Draw the final run of pixels */		draw_vertical_run(&x1, &y1, final_pixel_count, 				  x_advance, r, g, b, surface);		return;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -