core: Remove GP_ContextDump().
[gfxprim.git] / libs / core / GP_Context.c
blob3226c1c69a9ffcd5295f07fac86153a3418b8da9
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-2011 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
21 * *
22 * Copyright (C) 2009-2011 Cyril Hrubis <metan@ucw.cz> *
23 * *
24 *****************************************************************************/
26 #include "GP_Core.h"
27 #include "GP_Blit.h"
29 #include <string.h>
31 GP_Context *GP_ContextCopy(const GP_Context *src, int flag)
33 GP_Context *new;
34 uint8_t *pixels;
36 if (src == NULL)
37 return NULL;
39 new = malloc(sizeof(GP_Context));
40 pixels = malloc(src->bytes_per_row * src->h);
42 if (pixels == NULL || new == NULL) {
43 free(pixels);
44 free(new);
45 return NULL;
48 new->pixels = pixels;
50 if (flag)
51 memcpy(pixels, src->pixels, src->bytes_per_row * src->h);
53 new->bpp = src->bpp;
54 new->bytes_per_row = src->bytes_per_row;
55 new->offset = 0;
57 new->w = src->w;
58 new->h = src->h;
60 new->pixel_type = src->pixel_type;
61 new->bit_endian = src->bit_endian;
63 /* rotation and mirroring */
64 new->axes_swap = src->axes_swap;
65 new->y_swap = src->y_swap;
66 new->x_swap = src->x_swap;
68 new->free_pixels = 1;
70 return new;
73 static uint32_t get_bpr(uint32_t bpp, uint32_t w)
75 return (bpp * w) / 8 + !!((bpp * w) % 8);
78 GP_Context *GP_ContextAlloc(GP_Size w, GP_Size h, GP_PixelType type)
80 GP_CHECK_VALID_PIXELTYPE(type);
81 GP_Context *context = malloc(sizeof(GP_Context));
82 uint32_t bpp = GP_PixelSize(type);
83 uint32_t bpr = get_bpr(bpp, w);
84 void *pixels;
86 pixels = malloc(bpr * h);
88 if (pixels == NULL || context == NULL) {
89 free(pixels);
90 free(context);
91 return NULL;
94 context->pixels = pixels;
95 context->bpp = bpp;
96 context->bytes_per_row = bpr;
97 context->offset = 0;
99 context->w = w;
100 context->h = h;
102 context->pixel_type = type;
103 #warning Hmm, bit endianity... Why isn't this settled by different pixel types?
104 context->bit_endian = 0;
106 /* rotation and mirroring */
107 context->axes_swap = 0;
108 context->y_swap = 0;
109 context->x_swap = 0;
111 context->free_pixels = 1;
113 return context;
116 int GP_ContextResize(GP_Context *context, GP_Size w, GP_Size h)
118 uint32_t bpr = get_bpr(context->bpp, w);
119 void *pixels;
121 pixels = realloc(context->pixels, bpr * h);
123 if (pixels == NULL)
124 return 1;
126 context->w = w;
127 context->h = h;
128 context->bytes_per_row = bpr;
129 context->pixels = pixels;
131 return 0;
134 void GP_ContextInit(GP_Context *context, GP_Size w, GP_Size h,
135 GP_PixelType type, void *pixels)
137 uint32_t bpp = GP_PixelSize(type);
138 uint32_t bpr = get_bpr(bpp, w);
140 context->pixels = pixels;
141 context->bpp = bpp;
142 context->bytes_per_row = bpr;
143 context->offset = 0;
145 context->w = w;
146 context->h = h;
148 context->pixel_type = type;
149 context->bit_endian = 0;
151 /* rotation and mirroring */
152 context->axes_swap = 0;
153 context->y_swap = 0;
154 context->x_swap = 0;
156 context->free_pixels = 0;
159 GP_Context *GP_ContextConvert(const GP_Context *src,
160 GP_PixelType dst_pixel_type)
162 int w = GP_ContextW(src);
163 int h = GP_ContextH(src);
164 GP_Context *ret = GP_ContextAlloc(w, h, dst_pixel_type);
165 if (ret == NULL)
166 return NULL;
168 GP_Blit(src, 0, 0, w, h, ret, 0, 0);
169 return ret;
172 void GP_ContextFree(GP_Context *context)
174 if (context == NULL)
175 return;
177 if (context->free_pixels)
178 free(context->pixels);
180 free(context);
183 GP_Context *GP_ContextSubContext(GP_Context *context, GP_Context *subcontext,
184 GP_Coord x, GP_Coord y, GP_Size w, GP_Size h)
186 GP_CHECK(context, "NULL context");
188 GP_TRANSFORM_RECT(context, x, y, w, h);
190 GP_CHECK(context->w >= x + w, "Subcontext w out of original context.");
191 GP_CHECK(context->h >= y + h, "Subcontext h out of original context.");
193 GP_Context *ret = subcontext;
195 if (ret == NULL) {
196 ret = malloc(sizeof(GP_Context));
198 if (ret == NULL)
199 return NULL;
202 ret->bpp = context->bpp;
203 ret->bytes_per_row = context->bytes_per_row;
204 ret->offset = (context->offset +
205 GP_PixelAddrOffset(x, context->pixel_type)) % 8;
207 ret->w = w;
208 ret->h = h;
210 ret->pixel_type = context->pixel_type;
211 ret->bit_endian = context->bit_endian;
213 /* rotation and mirroring */
214 ret->axes_swap = context->axes_swap;
215 ret->y_swap = context->y_swap;
216 ret->x_swap = context->x_swap;
218 ret->pixels = GP_PIXEL_ADDR(context, x, y);
220 ret->free_pixels = 0;
222 return ret;
226 * The context rotations consists of two cyclic permutation groups that are
227 * mirrored.
229 * The flags change as follows:
231 * One group:
233 * x_swap y_swap axes_swap
234 * 0 0 0
235 * 1 0 1
236 * 1 1 0
237 * 0 1 1
239 * And mirrored group:
241 * x_swap y_swap axes_swap
242 * 0 0 1
243 * 1 0 0
244 * 1 1 1
245 * 0 1 0
248 void GP_ContextFlagsRotateCW(GP_Context *context)
250 context->axes_swap = !context->axes_swap;
252 if (!context->x_swap && !context->y_swap) {
253 context->x_swap = 1;
254 return;
257 if (context->x_swap && !context->y_swap) {
258 context->y_swap = 1;
259 return;
262 if (context->x_swap && context->y_swap) {
263 context->x_swap = 0;
264 return;
267 context->y_swap = 0;
270 void GP_ContextFlagsRotateCCW(GP_Context *context)
272 context->axes_swap = !context->axes_swap;
274 if (!context->x_swap && !context->y_swap) {
275 context->y_swap = 1;
276 return;
279 if (context->x_swap && !context->y_swap) {
280 context->x_swap = 0;
281 return;
284 if (context->x_swap && context->y_swap) {
285 context->y_swap = 0;
286 return;
289 context->x_swap = 1;