loaders: PNG: Handle gamma on 16bpp conversion
[gfxprim.git] / libs / gfx / GP_LineClip.c
blob570a2e31b514b417e4a2efbc27a06e90320c3d89
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-2010 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
21 * *
22 * Copyright (C) 2009-2010 Cyril Hrubis <metan@ucw.cz> *
23 * *
24 *****************************************************************************/
26 #include "core/GP_Common.h"
27 #include "core/GP_Types.h"
28 #include "gfx/GP_LineClip.h"
30 int GP_LineClip(int *px0, int *py0, int *px1, int *py1, int xmax, int ymax)
32 float x0 = (float) *px0;
33 float y0 = (float) *py0;
34 float x1 = (float) *px1;
35 float y1 = (float) *py1;
37 /* horizontal and vertical line are special cases */
38 if (y0 == y1) {
40 /* orient the line from left to right */
41 if (x1 < x0) {
42 GP_SWAP(x0, x1);
43 GP_SWAP(y0, y1);
46 /* check if it is not completely outside */
47 if (x1 < 0 || x0 > xmax || y0 < 0 || y0 > ymax)
48 return 0;
50 x0 = GP_MAX(x0, 0);
51 x1 = GP_MIN(x1, xmax);
52 goto give_result;
54 if (x0 == x1) {
56 /* orient the line from top to down */
57 if (x1 < x0) {
58 GP_SWAP(x0, x1);
59 GP_SWAP(y0, y1);
62 /* check if it is not completely outside */
63 if (y1 < 0 || y0 > ymax || x0 < 0 || x0 > xmax)
64 return 0;
66 /* clip it to the valid range */
67 y0 = GP_MAX(y0, 0);
68 y1 = GP_MIN(y1, ymax);
69 goto give_result;
72 /* orient the line from left to right */
73 if (x1 < x0) {
74 GP_SWAP(x0, x1);
75 GP_SWAP(y0, y1);
78 if (x1 < 0 || x0 > xmax || (y0 < 0 && y1 < 0) || (y0 > ymax && y1 > ymax)) {
80 /* the line lies completely outside the rectangle */
81 return 0;
84 float dx = (float)(x1 - x0);
85 float dy = (float)(y1 - y0);
86 float dyx = dy/dx;
87 float dxy = dx/dy;
89 /* clip the line against the left and right side of the rectangle */
90 if (x0 < 0) {
91 y0 = y0 - x0*dyx;
92 x0 = 0;
94 if (x1 > xmax) {
95 x1 = xmax;
96 y1 = y0 + (x1-x0)*dyx;
99 if (y0 < 0.0f) {
100 x0 = x0 - y0*dxy;
101 y0 = 0.0f;
102 } else if (y0 > ymax) {
103 x0 = x0 + (ymax-y0)*dxy;
104 y0 = ymax;
107 if (y1 < 0.0f) {
108 x1 = x1 - y1*dxy;
109 y1 = 0.0f;
111 else if (y1 > ymax) {
112 x1 = x1 - (y1 - ymax)*dxy;
113 y1 = ymax;
116 if (x0 < 0 || x0 > xmax || x1 < 0 || x1 > xmax) {
118 /* the line misses the clip rectangle around the corner */
119 return 0;
122 give_result:
124 *px0 = (int) x0;
125 *py0 = (int) y0;
126 *px1 = (int) x1;
127 *py1 = (int) y1;
128 return 1;