backends: Add support for timers to backends.
[gfxprim/pasky.git] / libs / gfx / GP_RectAA.c
blob812c6bd1e2ed5503759dee116d8eccfdf099b479
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include "core/GP_Transform.h"
24 #include "core/GP_GetPutPixel.h"
25 #include "core/GP_MixPixels.h"
26 #include "core/GP_FixedPoint.h"
27 #include "core/GP_GammaCorrection.h"
28 #include "GP_Rect.h"
29 #include "GP_RectAA.h"
33 void GP_FillRectXYXY_AA_Raw(GP_Context *context, GP_Coord x0, GP_Coord y0,
34 GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
36 GP_CHECK_CONTEXT(context);
38 if (x0 > x1)
39 GP_SWAP(x0, x1);
41 if (y0 > y1)
42 GP_SWAP(y0, y1);
44 /* Outer coordinates */
45 GP_Coord out_x0 = GP_FP_FLOOR_TO_INT(x0 + GP_FP_1_2);
46 GP_Coord out_y0 = GP_FP_FLOOR_TO_INT(y0 + GP_FP_1_2);
47 GP_Coord out_x1 = GP_FP_CEIL_TO_INT(x1 - GP_FP_1_2);
48 GP_Coord out_y1 = GP_FP_CEIL_TO_INT(y1 - GP_FP_1_2);
50 /* Size */
51 GP_Size w = x1 - x0;
52 GP_Size h = y1 - y0;
54 /* Special case, vertical 1px line */
55 if (out_x0 == out_x1) {
56 uint8_t mix = w;
57 GP_Coord i;
59 /* Special case 1px 100% width line */
60 if (w == GP_FP_1)
61 mix = 255;
63 for (i = out_y0; i <= out_y1; i++) {
64 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, out_x0, i);
65 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
66 GP_PutPixel_Raw_Clipped(context, out_x0, i, p);
69 return;
72 /* Special case, horizontal 1px line */
73 if (out_y0 == out_y1) {
74 uint8_t mix = w;
75 GP_Coord i;
77 /* Special case 1px 100% height line */
78 if (h == GP_FP_1)
79 mix = 255;
81 for (i = out_x0; i <= out_x1; i++) {
82 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, i, out_y0);
83 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
84 GP_PutPixel_Raw_Clipped(context, i, out_y0, p);
87 return;
90 /* This are integer coordinates of the "inner" rectangle */
91 GP_Coord in_x0 = GP_FP_CEIL_TO_INT(x0 + GP_FP_1_2);
92 GP_Coord in_y0 = GP_FP_CEIL_TO_INT(y0 + GP_FP_1_2);
93 GP_Coord in_x1 = GP_FP_FLOOR_TO_INT(x1 - GP_FP_1_2);
94 GP_Coord in_y1 = GP_FP_FLOOR_TO_INT(y1 - GP_FP_1_2);
96 /*
97 * Draw the inner rectanle in 100% intensity.
99 * Note that if out_x0 == in_x1 is 2px wide and both lines has less than
100 * 100% intensity. The same goes for out_y0 == in_y1.
102 if (in_x1 >= in_x0 && (out_x0 != in_x1 || out_x1 != in_x0)
103 && in_y1 >= in_y0 && (out_y0 != in_y1 || out_y1 != in_y0))
104 GP_FillRectXYXY_Raw(context, in_x0, in_y0, in_x1, in_y1, pixel);
106 /* if the outer and innter coordinates doesn't match, draw blurred edge */
107 if (in_y0 != out_y0) {
108 uint8_t mix = GP_FP_FROM_INT(in_y0) + GP_FP_1_2 - y0;
109 GP_Coord i;
111 for (i = out_x0; i <= out_x1; i++) {
112 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, i, out_y0);
113 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
114 GP_PutPixel_Raw_Clipped(context, i, out_y0, p);
118 if (in_y1 != out_y1) {
119 uint8_t mix = y1 - GP_FP_FROM_INT(in_y0) - GP_FP_1_2;
120 GP_Coord i;
122 for (i = out_x0; i <= out_x1; i++) {
123 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, i, out_y1);
124 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
125 GP_PutPixel_Raw_Clipped(context, i, out_y1, p);
129 if (in_x0 != out_x0) {
130 uint8_t mix = GP_FP_FROM_INT(in_x0) + GP_FP_1_2 - x0;
131 GP_Coord i;
133 for (i = out_y0; i <= out_y1; i++) {
134 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, out_x0, i);
135 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
136 GP_PutPixel_Raw_Clipped(context, out_x0, i, p);
140 if (in_x1 != out_x1) {
141 uint8_t mix = x1 - GP_FP_FROM_INT(in_x1) - GP_FP_1_2;
142 GP_Coord i;
144 for (i = out_y0; i <= out_y1; i++) {
145 GP_Pixel p = GP_GetPixel_Raw_Clipped(context, out_x1, i);
146 p = GP_MixPixels(pixel, p, mix, context->pixel_type);
147 GP_PutPixel_Raw_Clipped(context, out_x1, i, p);
151 //TODO four corner pixels!!!
154 void GP_FillRectXYWH_AA_Raw(GP_Context *context, GP_Coord x, GP_Coord y,
155 GP_Size w, GP_Size h, GP_Pixel pixel)
157 if (w == 0 || h == 0)
158 return;
160 GP_FillRectXYXY_AA_Raw(context, x, y,
161 x + w - GP_FP_1, y + h - GP_FP_1, pixel);
164 void GP_FillRectXYXY_AA(GP_Context *context, GP_Coord x0, GP_Coord y0,
165 GP_Coord x1, GP_Coord y1, GP_Pixel pixel)
167 GP_CHECK_CONTEXT(context);
169 GP_TRANSFORM_POINT_FP(context, x0, y0);
170 GP_TRANSFORM_POINT_FP(context, x1, y1);
172 GP_FillRectXYXY_AA_Raw(context, x0, y0, x1, y1, pixel);
175 void GP_FillRectXYWH_AA(GP_Context *context, GP_Coord x, GP_Coord y,
176 GP_Size w, GP_Size h, GP_Pixel pixel)
178 if (w == 0 || h == 0)
179 return;
181 GP_FillRectXYXY_AA(context, x, y,
182 x + w - GP_FP_1, y + h - GP_FP_1, pixel);