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