1 /*****************************************************************************
2 * This file is part of gfxprim library. *
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. *
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. *
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 *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
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"
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
);
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
);
54 /* Special case, vertical 1px line */
55 if (out_x0
== out_x1
) {
59 /* Special case 1px 100% width line */
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
);
72 /* Special case, horizontal 1px line */
73 if (out_y0
== out_y1
) {
77 /* Special case 1px 100% height line */
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
);
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
);
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
;
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
;
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
;
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
;
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)
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)
181 GP_FillRectXYXY_AA(context
, x
, y
,
182 x
+ w
- GP_FP_1
, y
+ h
- GP_FP_1
, pixel
);