eliminated gcc-4 compilation warnings
[wmaker-crm.git] / wrlib / raster.c
blob4c1719c3ce08a1a6eded1dceba388959438924af
1 /* raster.c - main and other misc stuff
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <config.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <X11/Xlib.h>
28 #include "wraster.h"
30 #include <assert.h>
33 char *WRasterLibVersion="0.9";
35 int RErrorCode=RERR_NONE;
38 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
41 #define MAX_WIDTH 20000
42 #define MAX_HEIGHT 20000
43 /* 20000^2*4 < 2G */
46 RImage*
47 RCreateImage(unsigned width, unsigned height, int alpha)
49 RImage *image=NULL;
51 assert(width>0 && height>0);
53 if (width > MAX_WIDTH || height > MAX_HEIGHT) {
54 RErrorCode = RERR_NOMEMORY;
55 return NULL;
58 image = malloc(sizeof(RImage));
59 if (!image) {
60 RErrorCode = RERR_NOMEMORY;
61 return NULL;
64 memset(image, 0, sizeof(RImage));
65 image->width = width;
66 image->height = height;
67 image->format = alpha ? RRGBAFormat : RRGBFormat;
68 image->refCount = 1;
70 /* the +4 is to give extra bytes at the end of the buffer,
71 * so that we can optimize image conversion for MMX(tm).. see convert.c
73 image->data = malloc(width * height * (alpha ? 4 : 3) + 4);
74 if (!image->data) {
75 RErrorCode = RERR_NOMEMORY;
76 free(image);
77 image = NULL;
80 return image;
85 RImage*
86 RRetainImage(RImage *image)
88 if (image)
89 image->refCount++;
91 return image;
95 void
96 RReleaseImage(RImage *image)
98 assert(image!=NULL);
100 image->refCount--;
102 if (image->refCount < 1) {
103 free(image->data);
104 free(image);
109 RImage*
110 RCloneImage(RImage *image)
112 RImage *new_image;
114 assert(image!=NULL);
116 new_image = RCreateImage(image->width, image->height, HAS_ALPHA(image));
117 if (!new_image)
118 return NULL;
120 new_image->background = image->background;
121 memcpy(new_image->data, image->data,
122 image->width*image->height*(HAS_ALPHA(image) ? 4 : 3));
124 return new_image;
128 RImage*
129 RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
131 int i, ofs;
132 RImage *new_image;
133 unsigned total_line_size, line_size;
135 assert(image!=NULL);
136 assert(x>=0 && y>=0);
137 assert(x<image->width && y<image->height);
138 assert(width>0 && height>0);
140 if (x+width > image->width)
141 width = image->width-x;
142 if (y+height > image->height)
143 height = image->height-y;
145 new_image = RCreateImage(width, height, HAS_ALPHA(image));
147 if (!new_image)
148 return NULL;
149 new_image->background = image->background;
151 total_line_size = image->width * (HAS_ALPHA(image) ? 4 : 3);
152 line_size = width * (HAS_ALPHA(image) ? 4 : 3);
154 ofs = x*(HAS_ALPHA(image) ? 4 : 3) + y*total_line_size;;
156 for (i=0; i<height; i++) {
157 memcpy(&new_image->data[i*line_size],
158 &image->data[i*total_line_size+ofs], line_size);
160 return new_image;
165 *----------------------------------------------------------------------
166 * RCombineImages-
167 * Combines two equal sized images with alpha image. The second
168 * image will be placed on top of the first one.
169 *----------------------------------------------------------------------
171 void
172 RCombineImages(RImage *image, RImage *src)
174 assert(image->width == src->width);
175 assert(image->height == src->height);
177 if (!HAS_ALPHA(src)) {
178 if (!HAS_ALPHA(image)) {
179 memcpy(image->data, src->data, image->height*image->width*3);
180 } else {
181 int x, y;
182 unsigned char *d, *s;
184 d = image->data;
185 s = src->data;
186 for (y = 0; y < image->height; y++) {
187 for (x = 0; x < image->width; x++) {
188 *d++ = *s++;
189 *d++ = *s++;
190 *d++ = *s++;
191 d++;
195 } else {
196 register int i;
197 unsigned char *d;
198 unsigned char *s;
199 int alpha, calpha;
201 d = image->data;
202 s = src->data;
204 if (!HAS_ALPHA(image)) {
205 for (i=0; i<image->height*image->width; i++) {
206 alpha = *(s+3);
207 calpha = 255 - alpha;
208 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
209 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
210 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
211 s++;
213 } else {
214 for (i=0; i<image->height*image->width; i++) {
215 alpha = *(s+3);
216 calpha = 255 - alpha;
217 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
218 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
219 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
220 *d++ |= *s++;
229 void
230 RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
232 register int i;
233 unsigned char *d;
234 unsigned char *s;
235 int c_opaqueness;
237 assert(image->width == src->width);
238 assert(image->height == src->height);
240 d = image->data;
241 s = src->data;
243 c_opaqueness = 255 - opaqueness;
245 #define OP opaqueness
246 #define COP c_opaqueness
248 if (!HAS_ALPHA(src)) {
249 int dalpha = HAS_ALPHA(image);
250 for (i=0; i < image->width*image->height; i++) {
251 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
252 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
253 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
254 if (dalpha) {
255 d++;
258 } else {
259 int tmp;
261 if (!HAS_ALPHA(image)) {
262 for (i=0; i<image->width*image->height; i++) {
263 tmp = (*(s+3) * opaqueness)/256;
264 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
265 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
266 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
267 s++;
269 } else {
270 for (i=0; i<image->width*image->height; i++) {
271 tmp = (*(s+3) * opaqueness)/256;
272 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
273 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
274 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
275 *d |= tmp;
276 d++; s++;
280 #undef OP
281 #undef COP
285 calculateCombineArea(RImage *des, RImage *src, int *sx, int *sy,
286 unsigned int *swidth, unsigned int *sheight, int *dx, int *dy)
288 int width = (int)*swidth, height = (int)*sheight;
290 if (*dx < 0) {
291 *sx = -*dx;
292 width = width + *dx;
293 *dx = 0;
296 if (*dx + width > des->width) {
297 width = des->width - *dx;
300 if (*dy < 0) {
301 *sy = -*dy;
302 height = height + *dy;
303 *dy = 0;
306 if (*dy + height > des->height) {
307 height = des->height - *dy;
310 if (height>0 && width>0) {
311 *swidth = width;
312 *sheight = height;
313 return True;
316 return False;
319 void
320 RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
321 unsigned height, int dx, int dy)
323 int x, y, dwi, swi;
324 unsigned char *d;
325 unsigned char *s;
326 int alpha, calpha;
328 if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
329 return;
331 if (!HAS_ALPHA(src)) {
332 if (!HAS_ALPHA(image)) {
333 swi = src->width * 3;
334 dwi = image->width * 3;
336 s = src->data + (sy*(int)src->width + sx) * 3;
337 d = image->data + (dy*(int)image->width + dx) * 3;
339 for (y=0; y < height; y++) {
340 memcpy(d, s, width*3);
341 d += dwi;
342 s += swi;
344 } else {
345 swi = (src->width - width) * 3;
346 dwi = (image->width - width) * 4;
348 s = src->data + (sy*(int)src->width + sx) * 3;
349 d = image->data + (dy*(int)image->width + dx) * 4;
351 for (y=0; y < height; y++) {
352 for (x=0; x < width; x++) {
353 *d++ = *s++;
354 *d++ = *s++;
355 *d++ = *s++;
356 d++;
358 d += dwi;
359 s += swi;
362 } else {
363 int dalpha = HAS_ALPHA(image);
365 swi = (src->width - width) * 4;
366 s = src->data + (sy*(int)src->width + sx) * 4;
367 if (dalpha) {
368 dwi = (image->width - width) * 4;
369 d = image->data + (dy*(int)image->width + dx) * 4;
370 } else {
371 dwi = (image->width - width) * 3;
372 d = image->data + (dy*(int)image->width + dx) * 3;
375 for (y=0; y < height; y++) {
376 for (x=0; x < width; x++) {
377 alpha = *(s+3);
378 calpha = 255 - alpha;
379 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
380 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
381 *d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
382 s++;
383 if (dalpha)
384 d++;
386 d += dwi;
387 s += swi;
393 void
394 RCopyArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
395 unsigned height, int dx, int dy)
397 int x, y, dwi, swi;
398 unsigned char *d;
399 unsigned char *s;
401 if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
402 return;
404 if (!HAS_ALPHA(src)) {
405 if (!HAS_ALPHA(image)) {
406 swi = src->width * 3;
407 dwi = image->width * 3;
409 s = src->data + (sy*(int)src->width + sx) * 3;
410 d = image->data + (dy*(int)image->width + dx) * 3;
412 for (y=0; y < height; y++) {
413 memcpy(d, s, width*3);
414 d += dwi;
415 s += swi;
417 } else {
418 swi = (src->width - width) * 3;
419 dwi = (image->width - width) * 4;
421 s = src->data + (sy*(int)src->width + sx) * 3;
422 d = image->data + (dy*(int)image->width + dx) * 4;
424 for (y=0; y < height; y++) {
425 for (x=0; x < width; x++) {
426 *d++ = *s++;
427 *d++ = *s++;
428 *d++ = *s++;
429 d++;
431 d += dwi;
432 s += swi;
435 } else {
436 int dalpha = HAS_ALPHA(image);
438 swi = src->width * 4;
439 s = src->data + (sy*(int)src->width + sx) * 4;
440 if (dalpha) {
441 dwi = image->width * 4;
442 d = image->data + (dy*(int)image->width + dx) * 4;
443 } else {
444 dwi = image->width * 3;
445 d = image->data + (dy*(int)image->width + dx) * 3;
448 if (dalpha) {
449 for (y=0; y < height; y++) {
450 memcpy(d, s, width*4);
451 d += dwi;
452 s += swi;
454 } else {
455 for (y=0; y < height; y++) {
456 for (x=0; x < width; x++) {
457 *d++ = *s++;
458 *d++ = *s++;
459 *d++ = *s++;
460 s++;
462 d += dwi;
463 s += swi;
470 void
471 RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
472 unsigned width, unsigned height, int dx, int dy,
473 int opaqueness)
475 int x, y, dwi, swi;
476 int c_opaqueness;
477 unsigned char *s, *d;
478 int dalpha = HAS_ALPHA(image);
479 int dch = (dalpha ? 4 : 3);
481 if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
482 return;
484 d = image->data + (dy*image->width + dx) * dch;
485 dwi = (image->width - width)*dch;
487 c_opaqueness = 255 - opaqueness;
489 #define OP opaqueness
490 #define COP c_opaqueness
492 if (!HAS_ALPHA(src)) {
494 s = src->data + (sy*src->width + sx)*3;
495 swi = (src->width - width) * 3;
497 for (y=0; y < height; y++) {
498 for (x=0; x < width; x++) {
499 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
500 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
501 *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
502 if (dalpha)
503 d++;
505 d += dwi; s += swi;
507 } else {
508 int tmp;
510 s = src->data + (sy*src->width + sx)*4;
511 swi = (src->width - width) * 4;
513 for (y=0; y < height; y++) {
514 for (x=0; x < width; x++) {
515 tmp = (*(s+3) * opaqueness)/256;
516 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
517 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
518 *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
519 s++;
520 if (dalpha)
521 d++;
523 d += dwi; s += swi;
526 #undef OP
527 #undef COP
532 void
533 RCombineImageWithColor(RImage *image, RColor *color)
535 register int i;
536 unsigned char *d;
537 int alpha, nalpha, r, g, b;
539 d = image->data;
541 if (!HAS_ALPHA(image)) {
542 /* Image has no alpha channel, so we consider it to be all 255.
543 * Thus there are no transparent parts to be filled. */
544 return;
546 r = color->red;
547 g = color->green;
548 b = color->blue;
550 for (i=0; i < image->width*image->height; i++) {
551 alpha = *(d+3);
552 nalpha = 255 - alpha;
554 *d = (((int)*d * alpha) + (r * nalpha))/256; d++;
555 *d = (((int)*d * alpha) + (g * nalpha))/256; d++;
556 *d = (((int)*d * alpha) + (b * nalpha))/256; d++;
557 d++;
564 RImage*
565 RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
567 int x, y;
568 unsigned w;
569 unsigned long tile_size = tile->width * tile->height;
570 unsigned long tx = 0;
571 RImage *image;
572 unsigned char *s, *d;
574 if (width == tile->width && height == tile->height)
575 image = RCloneImage(tile);
576 else if (width <= tile->width && height <= tile->height)
577 image = RGetSubImage(tile, 0, 0, width, height);
578 else {
579 int has_alpha = HAS_ALPHA(tile);
581 image = RCreateImage(width, height, has_alpha);
583 d = image->data;
584 s = tile->data;
586 for (y = 0; y < height; y++) {
587 for (x = 0; x < width; x += tile->width) {
589 w = (width - x < tile->width) ? width - x : tile->width;
591 if (has_alpha) {
592 w *= 4;
593 memcpy(d, s+tx*4, w);
594 } else {
595 w *= 3;
596 memcpy(d, s+tx*3, w);
598 d += w;
601 tx = (tx + tile->width) % tile_size;
604 return image;
608 RImage*
609 RMakeCenteredImage(RImage *image, unsigned width, unsigned height, RColor *color)
611 int x, y, w, h, sx, sy;
612 RImage *tmp;
614 tmp = RCreateImage(width, height, False);
615 if (!tmp) {
616 return NULL;
619 RClearImage(tmp, color);
621 if (image->height < height) {
622 h = image->height;
623 y = (height - h)/2;
624 sy = 0;
625 } else {
626 sy = (image->height - height)/2;
627 y = 0;
628 h = height;
630 if (image->width < width) {
631 w = image->width;
632 x = (width - w)/2;
633 sx = 0;
634 } else {
635 sx = (image->width - width)/2;
636 x = 0;
637 w = width;
639 RCombineArea(tmp, image, sx, sy, w, h, x, y);
641 return tmp;