1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/*
* libcucul Canvas for ultrafast compositing of Unicode letters
* Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* $Id: triangle.c 1026 2006-11-11 16:29:39Z sam $
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Do What The Fuck You Want To
* Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
* This file contains triangle drawing functions, both filled and outline.
*/
#include "config.h"
#include "common.h"
#if !defined(__KERNEL__)
# include <stdlib.h>
#endif
#include "cucul.h"
#include "cucul_internals.h"
/** \brief Draw a triangle on the canvas using the given character.
*
* This function never fails.
*
* \param cv The handle to the libcucul canvas.
* \param x1 X coordinate of the first point.
* \param y1 Y coordinate of the first point.
* \param x2 X coordinate of the second point.
* \param y2 Y coordinate of the second point.
* \param x3 X coordinate of the third point.
* \param y3 Y coordinate of the third point.
* \param ch UTF-32 character to be used to draw the triangle outline.
* \return This function always returns 0.
*/
int cucul_draw_triangle(cucul_canvas_t *cv, int x1, int y1, int x2, int y2,
int x3, int y3, unsigned long int ch)
{
cucul_draw_line(cv, x1, y1, x2, y2, ch);
cucul_draw_line(cv, x2, y2, x3, y3, ch);
cucul_draw_line(cv, x3, y3, x1, y1, ch);
return 0;
}
/** \brief Draw a thin triangle on the canvas.
*
* This function never fails.
*
* \param cv The handle to the libcucul canvas.
* \param x1 X coordinate of the first point.
* \param y1 Y coordinate of the first point.
* \param x2 X coordinate of the second point.
* \param y2 Y coordinate of the second point.
* \param x3 X coordinate of the third point.
* \param y3 Y coordinate of the third point.
* \return This function always returns 0.
*/
int cucul_draw_thin_triangle(cucul_canvas_t *cv, int x1, int y1,
int x2, int y2, int x3, int y3)
{
cucul_draw_thin_line(cv, x1, y1, x2, y2);
cucul_draw_thin_line(cv, x2, y2, x3, y3);
cucul_draw_thin_line(cv, x3, y3, x1, y1);
return 0;
}
/** \brief Fill a triangle on the canvas using the given character.
*
* This function never fails.
*
* \param cv The handle to the libcucul canvas.
* \param x1 X coordinate of the first point.
* \param y1 Y coordinate of the first point.
* \param x2 X coordinate of the second point.
* \param y2 Y coordinate of the second point.
* \param x3 X coordinate of the third point.
* \param y3 Y coordinate of the third point.
* \param ch UTF-32 character to be used to fill the triangle.
* \return This function always returns 0.
*/
int cucul_fill_triangle(cucul_canvas_t *cv, int x1, int y1, int x2, int y2,
int x3, int y3, unsigned long int ch)
{
int x, y, xmin, xmax, ymin, ymax;
long int xx1, xx2, xa, xb, sl21, sl31, sl32;
/* Bubble-sort y1 <= y2 <= y3 */
if(y1 > y2)
return cucul_fill_triangle(cv, x2, y2, x1, y1, x3, y3, ch);
if(y2 > y3)
return cucul_fill_triangle(cv, x1, y1, x3, y3, x2, y2, ch);
/* Compute slopes and promote precision */
sl21 = (y2 == y1) ? 0 : (x2 - x1) * 0x10000 / (y2 - y1);
sl31 = (y3 == y1) ? 0 : (x3 - x1) * 0x10000 / (y3 - y1);
sl32 = (y3 == y2) ? 0 : (x3 - x2) * 0x10000 / (y3 - y2);
x1 *= 0x10000;
x2 *= 0x10000;
x3 *= 0x10000;
ymin = y1 < 0 ? 0 : y1;
ymax = y3 + 1 < (int)cv->height ? y3 + 1 : (int)cv->height;
if(ymin < y2)
{
xa = x1 + sl21 * (ymin - y1);
xb = x1 + sl31 * (ymin - y1);
}
else if(ymin == y2)
{
xa = x2;
xb = (y1 == y3) ? x3 : x1 + sl31 * (ymin - y1);
}
else /* (ymin > y2) */
{
xa = x3 + sl32 * (ymin - y3);
xb = x3 + sl31 * (ymin - y3);
}
/* Rasterize our triangle */
for(y = ymin; y < ymax; y++)
{
/* Rescale xa and xb, recentering the division */
if(xa < xb)
{
xx1 = (xa + 0x800) / 0x10000;
xx2 = (xb + 0x801) / 0x10000;
}
else
{
xx1 = (xb + 0x800) / 0x10000;
xx2 = (xa + 0x801) / 0x10000;
}
xmin = xx1 < 0 ? 0 : xx1;
xmax = xx2 + 1 < (int)cv->width ? xx2 + 1 : (int)cv->width;
for(x = xmin; x < xmax; x++)
cucul_put_char(cv, x, y, ch);
xa += y < y2 ? sl21 : sl32;
xb += sl31;
}
return 0;
}
|