]> Dogcows Code - chaz/openbox/blob - otk/image.cc
make shape work with the titlebar and handle
[chaz/openbox] / otk / image.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #ifdef HAVE_STDIO_H
8 # include <stdio.h>
9 #endif // HAVE_STDIO_H
10
11 #include <algorithm>
12 using std::max;
13 using std::min;
14
15 #include "display.hh"
16 #include "gccache.hh"
17 #include "image.hh"
18 #include "texture.hh"
19
20 namespace otk {
21
22 BImage::BImage(BImageControl *c, int w, int h) {
23 control = c;
24
25 width = (w > 0) ? w : 1;
26 height = (h > 0) ? h : 1;
27
28 red = new unsigned char[width * height];
29 green = new unsigned char[width * height];
30 blue = new unsigned char[width * height];
31
32 xtable = ytable = (unsigned int *) 0;
33
34 cpc = control->getColorsPerChannel();
35 cpccpc = cpc * cpc;
36
37 control->getColorTables(&red_table, &green_table, &blue_table,
38 &red_offset, &green_offset, &blue_offset,
39 &red_bits, &green_bits, &blue_bits);
40
41 if (control->getVisual()->c_class != TrueColor)
42 control->getXColorTable(&colors, &ncolors);
43 }
44
45
46 BImage::~BImage(void) {
47 delete [] red;
48 delete [] green;
49 delete [] blue;
50 }
51
52
53 Pixmap BImage::render(const BTexture &texture) {
54 if (texture.texture() & BTexture::Parent_Relative)
55 return ParentRelative;
56 else if (texture.texture() & BTexture::Solid)
57 return render_solid(texture);
58 else if (texture.texture() & BTexture::Gradient)
59 return render_gradient(texture);
60 return None;
61 }
62
63
64 Pixmap BImage::render_solid(const BTexture &texture) {
65 Pixmap pixmap = XCreatePixmap(OBDisplay::display,
66 control->getDrawable(), width,
67 height, control->getDepth());
68 if (pixmap == None) {
69 fprintf(stderr, "BImage::render_solid: error creating pixmap\n");
70 return None;
71 }
72
73 BPen pen(texture.color());
74 BPen penlight(texture.lightColor());
75 BPen penshadow(texture.shadowColor());
76
77 XFillRectangle(OBDisplay::display, pixmap, pen.gc(), 0, 0, width, height);
78
79 if (texture.texture() & BTexture::Interlaced) {
80 BPen peninterlace(texture.colorTo());
81 for (unsigned int i = 0; i < height; i += 2)
82 XDrawLine(OBDisplay::display, pixmap, peninterlace.gc(), 0, i, width, i);
83 }
84
85 int left = 0, top = 0, right = width - 1, bottom = height - 1;
86
87 if (texture.texture() & BTexture::Border) {
88 BPen penborder(texture.borderColor());
89 XDrawRectangle(OBDisplay::display, pixmap, penborder.gc(),
90 left, top, right, bottom);
91 }
92
93 if (texture.texture() & BTexture::Bevel1) {
94 if (texture.texture() & BTexture::Raised) {
95 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
96 left, bottom, right, bottom);
97 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
98 right, bottom, right, top);
99
100 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
101 left, top, right, top);
102 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
103 left, bottom, left, top);
104 } else if (texture.texture() & BTexture::Sunken) {
105 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
106 left, bottom, right, bottom);
107 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
108 right, bottom, right, top);
109
110 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
111 left, top, right, top);
112 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
113 left, bottom, left, top);
114 }
115 } else if (texture.texture() & BTexture::Bevel2) {
116 if (texture.texture() & BTexture::Raised) {
117 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
118 left + 1, bottom - 2, right - 2, bottom - 2);
119 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
120 right - 2, bottom - 2, right - 2, top + 1);
121
122 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
123 left + 1, top + 1, right - 2, top + 1);
124 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
125 left + 1, bottom - 2, left + 1, top + 1);
126 } else if (texture.texture() & BTexture::Sunken) {
127 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
128 left + 1, bottom - 2, right - 2, bottom - 2);
129 XDrawLine(OBDisplay::display, pixmap, penlight.gc(),
130 right - 2, bottom - 2, right - 2, top + 1);
131
132 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
133 left + 1, top + 1, right - 2, top + 1);
134 XDrawLine(OBDisplay::display, pixmap, penshadow.gc(),
135 left + 1, bottom - 2, left + 1, top + 1);
136 }
137 }
138
139 return pixmap;
140 }
141
142
143 Pixmap BImage::render_gradient(const BTexture &texture) {
144 bool inverted = False;
145
146 interlaced = texture.texture() & BTexture::Interlaced;
147
148 if (texture.texture() & BTexture::Sunken) {
149 from = texture.colorTo();
150 to = texture.color();
151
152 if (! (texture.texture() & BTexture::Invert)) inverted = True;
153 } else {
154 from = texture.color();
155 to = texture.colorTo();
156
157 if (texture.texture() & BTexture::Invert) inverted = True;
158 }
159
160 control->getGradientBuffers(width, height, &xtable, &ytable);
161
162 if (texture.texture() & BTexture::Diagonal) dgradient();
163 else if (texture.texture() & BTexture::Elliptic) egradient();
164 else if (texture.texture() & BTexture::Horizontal) hgradient();
165 else if (texture.texture() & BTexture::Pyramid) pgradient();
166 else if (texture.texture() & BTexture::Rectangle) rgradient();
167 else if (texture.texture() & BTexture::Vertical) vgradient();
168 else if (texture.texture() & BTexture::CrossDiagonal) cdgradient();
169 else if (texture.texture() & BTexture::PipeCross) pcgradient();
170
171 if (texture.texture() & BTexture::Bevel1) bevel1();
172 else if (texture.texture() & BTexture::Bevel2) bevel2();
173
174 if (texture.texture() & BTexture::Border) border(texture);
175
176 if (inverted) invert();
177
178 return renderPixmap();
179
180 }
181
182
183 static const unsigned char dither4[4][4] = {
184 {0, 4, 1, 5},
185 {6, 2, 7, 3},
186 {1, 5, 0, 4},
187 {7, 3, 6, 2}
188 };
189
190
191 /*
192 * Helper function for TrueColorDither and renderXImage
193 *
194 * This handles the proper setting of the image data based on the image depth
195 * and the machine's byte ordering
196 */
197 static inline
198 void assignPixelData(unsigned int bit_depth, unsigned char **data,
199 unsigned long pixel) {
200 unsigned char *pixel_data = *data;
201 switch (bit_depth) {
202 case 8: // 8bpp
203 *pixel_data++ = pixel;
204 break;
205
206 case 16: // 16bpp LSB
207 *pixel_data++ = pixel;
208 *pixel_data++ = pixel >> 8;
209 break;
210
211 case 17: // 16bpp MSB
212 *pixel_data++ = pixel >> 8;
213 *pixel_data++ = pixel;
214 break;
215
216 case 24: // 24bpp LSB
217 *pixel_data++ = pixel;
218 *pixel_data++ = pixel >> 8;
219 *pixel_data++ = pixel >> 16;
220 break;
221
222 case 25: // 24bpp MSB
223 *pixel_data++ = pixel >> 16;
224 *pixel_data++ = pixel >> 8;
225 *pixel_data++ = pixel;
226 break;
227
228 case 32: // 32bpp LSB
229 *pixel_data++ = pixel;
230 *pixel_data++ = pixel >> 8;
231 *pixel_data++ = pixel >> 16;
232 *pixel_data++ = pixel >> 24;
233 break;
234
235 case 33: // 32bpp MSB
236 *pixel_data++ = pixel >> 24;
237 *pixel_data++ = pixel >> 16;
238 *pixel_data++ = pixel >> 8;
239 *pixel_data++ = pixel;
240 break;
241 }
242 *data = pixel_data; // assign back so we don't lose our place
243 }
244
245
246 // algorithm: ordered dithering... many many thanks to rasterman
247 // (raster@rasterman.com) for telling me about this... portions of this
248 // code is based off of his code in Imlib
249 void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line,
250 unsigned char *pixel_data) {
251 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
252 unsigned char *ppixel_data = pixel_data;
253 unsigned long pixel;
254
255 for (y = 0, offset = 0; y < height; y++) {
256 dithy = y & 0x3;
257
258 for (x = 0; x < width; x++, offset++) {
259 dithx = x & 0x3;
260 r = red[offset];
261 g = green[offset];
262 b = blue[offset];
263
264 er = r & (red_bits - 1);
265 eg = g & (green_bits - 1);
266 eb = b & (blue_bits - 1);
267
268 r = red_table[r];
269 g = green_table[g];
270 b = blue_table[b];
271
272 if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
273 if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
274 if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
275
276 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
277 assignPixelData(bit_depth, &pixel_data, pixel);
278 }
279
280 pixel_data = (ppixel_data += bytes_per_line);
281 }
282 }
283
284 #ifdef ORDEREDPSEUDO
285 const static unsigned char dither8[8][8] = {
286 { 0, 32, 8, 40, 2, 34, 10, 42},
287 { 48, 16, 56, 24, 50, 18, 58, 26},
288 { 12, 44, 4, 36, 14, 46, 6, 38},
289 { 60, 28, 52, 20, 62, 30, 54, 22},
290 { 3, 35, 11, 43, 1, 33, 9, 41},
291 { 51, 19, 59, 27, 49, 17, 57, 25},
292 { 15, 47, 7, 39, 13, 45, 5, 37},
293 { 63, 31, 55, 23, 61, 29, 53, 21}
294 };
295
296 void BImage::OrderedPseudoColorDither(int bytes_per_line,
297 unsigned char *pixel_data) {
298 unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset;
299 unsigned long pixel;
300 unsigned char *ppixel_data = pixel_data;
301
302 for (y = 0, offset = 0; y < height; y++) {
303 dithy = y & 7;
304
305 for (x = 0; x < width; x++, offset++) {
306 dithx = x & 7;
307
308 r = red[offset];
309 g = green[offset];
310 b = blue[offset];
311
312 er = r & (red_bits - 1);
313 eg = g & (green_bits - 1);
314 eb = b & (blue_bits - 1);
315
316 r = red_table[r];
317 g = green_table[g];
318 b = blue_table[b];
319
320 if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
321 if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
322 if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
323
324 pixel = (r * cpccpc) + (g * cpc) + b;
325 *(pixel_data++) = colors[pixel].pixel;
326 }
327
328 pixel_data = (ppixel_data += bytes_per_line);
329 }
330 }
331 #endif
332
333 void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) {
334 short *terr,
335 *rerr = new short[width + 2],
336 *gerr = new short[width + 2],
337 *berr = new short[width + 2],
338 *nrerr = new short[width + 2],
339 *ngerr = new short[width + 2],
340 *nberr = new short[width + 2];
341
342 int rr, gg, bb, rer, ger, ber;
343 int dd = 255 / control->getColorsPerChannel();
344 unsigned int x, y, r, g, b, offset;
345 unsigned long pixel;
346 unsigned char *ppixel_data = pixel_data;
347
348 for (x = 0; x < width; x++) {
349 *(rerr + x) = *(red + x);
350 *(gerr + x) = *(green + x);
351 *(berr + x) = *(blue + x);
352 }
353
354 *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
355
356 for (y = 0, offset = 0; y < height; y++) {
357 if (y < (height - 1)) {
358 int i = offset + width;
359 for (x = 0; x < width; x++, i++) {
360 *(nrerr + x) = *(red + i);
361 *(ngerr + x) = *(green + i);
362 *(nberr + x) = *(blue + i);
363 }
364
365 *(nrerr + x) = *(red + (--i));
366 *(ngerr + x) = *(green + i);
367 *(nberr + x) = *(blue + i);
368 }
369
370 for (x = 0; x < width; x++) {
371 rr = rerr[x];
372 gg = gerr[x];
373 bb = berr[x];
374
375 if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
376 if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
377 if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
378
379 r = red_table[rr];
380 g = green_table[gg];
381 b = blue_table[bb];
382
383 rer = rerr[x] - r*dd;
384 ger = gerr[x] - g*dd;
385 ber = berr[x] - b*dd;
386
387 pixel = (r * cpccpc) + (g * cpc) + b;
388 *pixel_data++ = colors[pixel].pixel;
389
390 r = rer >> 1;
391 g = ger >> 1;
392 b = ber >> 1;
393 rerr[x+1] += r;
394 gerr[x+1] += g;
395 berr[x+1] += b;
396 nrerr[x] += r;
397 ngerr[x] += g;
398 nberr[x] += b;
399 }
400
401 offset += width;
402
403 pixel_data = (ppixel_data += bytes_per_line);
404
405 terr = rerr;
406 rerr = nrerr;
407 nrerr = terr;
408
409 terr = gerr;
410 gerr = ngerr;
411 ngerr = terr;
412
413 terr = berr;
414 berr = nberr;
415 nberr = terr;
416 }
417
418 delete [] rerr;
419 delete [] gerr;
420 delete [] berr;
421 delete [] nrerr;
422 delete [] ngerr;
423 delete [] nberr;
424 }
425
426 XImage *BImage::renderXImage(void) {
427 XImage *image =
428 XCreateImage(OBDisplay::display,
429 control->getVisual(), control->getDepth(), ZPixmap, 0, 0,
430 width, height, 32, 0);
431
432 if (! image) {
433 fprintf(stderr, "BImage::renderXImage: error creating XImage\n");
434 return (XImage *) 0;
435 }
436
437 // insurance policy
438 image->data = (char *) 0;
439
440 unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
441
442 unsigned int o = image->bits_per_pixel +
443 ((image->byte_order == MSBFirst) ? 1 : 0);
444
445 bool unsupported = False;
446
447 if (control->doDither() && width > 1 && height > 1) {
448 switch (control->getVisual()->c_class) {
449 case TrueColor:
450 TrueColorDither(o, image->bytes_per_line, d);
451 break;
452
453 case StaticColor:
454 case PseudoColor: {
455 #ifdef ORDEREDPSEUDO
456 OrderedPseudoColorDither(image->bytes_per_line, d);
457 #else
458 PseudoColorDither(image->bytes_per_line, d);
459 #endif
460 break;
461 }
462
463 default:
464 unsupported = True;
465 }
466 } else {
467 unsigned int x, y, r, g, b, offset;
468 unsigned char *pixel_data = d, *ppixel_data = d;
469 unsigned long pixel;
470
471 switch (control->getVisual()->c_class) {
472 case StaticColor:
473 case PseudoColor:
474 for (y = 0, offset = 0; y < height; ++y) {
475 for (x = 0; x < width; ++x, ++offset) {
476 r = red_table[red[offset]];
477 g = green_table[green[offset]];
478 b = blue_table[blue[offset]];
479
480 pixel = (r * cpccpc) + (g * cpc) + b;
481 *pixel_data++ = colors[pixel].pixel;
482 }
483
484 pixel_data = (ppixel_data += image->bytes_per_line);
485 }
486
487 break;
488
489 case TrueColor:
490 for (y = 0, offset = 0; y < height; y++) {
491 for (x = 0; x < width; x++, offset++) {
492 r = red_table[red[offset]];
493 g = green_table[green[offset]];
494 b = blue_table[blue[offset]];
495
496 pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
497 assignPixelData(o, &pixel_data, pixel);
498 }
499
500 pixel_data = (ppixel_data += image->bytes_per_line);
501 }
502
503 break;
504
505 case StaticGray:
506 case GrayScale:
507 for (y = 0, offset = 0; y < height; y++) {
508 for (x = 0; x < width; x++, offset++) {
509 r = *(red_table + *(red + offset));
510 g = *(green_table + *(green + offset));
511 b = *(blue_table + *(blue + offset));
512
513 g = ((r * 30) + (g * 59) + (b * 11)) / 100;
514 *pixel_data++ = colors[g].pixel;
515 }
516
517 pixel_data = (ppixel_data += image->bytes_per_line);
518 }
519
520 break;
521
522 default:
523 unsupported = True;
524 }
525 }
526
527 if (unsupported) {
528 fprintf(stderr, "BImage::renderXImage: unsupported visual\n");
529 delete [] d;
530 XDestroyImage(image);
531 return (XImage *) 0;
532 }
533
534 image->data = (char *) d;
535
536 return image;
537 }
538
539
540 Pixmap BImage::renderPixmap(void) {
541 Pixmap pixmap =
542 XCreatePixmap(OBDisplay::display,
543 control->getDrawable(), width, height, control->getDepth());
544
545 if (pixmap == None) {
546 fprintf(stderr, "BImage::renderPixmap: error creating pixmap\n");
547 return None;
548 }
549
550 XImage *image = renderXImage();
551
552 if (! image) {
553 XFreePixmap(OBDisplay::display, pixmap);
554 return None;
555 }
556
557 if (! image->data) {
558 XDestroyImage(image);
559 XFreePixmap(OBDisplay::display, pixmap);
560 return None;
561 }
562
563 XPutImage(OBDisplay::display, pixmap,
564 DefaultGC(OBDisplay::display,
565 control->getScreenInfo()->getScreenNumber()),
566 image, 0, 0, 0, 0, width, height);
567
568 if (image->data) {
569 delete [] image->data;
570 image->data = NULL;
571 }
572
573 XDestroyImage(image);
574
575 return pixmap;
576 }
577
578
579 void BImage::bevel1(void) {
580 if (width > 2 && height > 2) {
581 unsigned char *pr = red, *pg = green, *pb = blue;
582
583 register unsigned char r, g, b, rr ,gg ,bb;
584 register unsigned int w = width, h = height - 1, wh = w * h;
585
586 while (--w) {
587 r = *pr;
588 rr = r + (r >> 1);
589 if (rr < r) rr = ~0;
590 g = *pg;
591 gg = g + (g >> 1);
592 if (gg < g) gg = ~0;
593 b = *pb;
594 bb = b + (b >> 1);
595 if (bb < b) bb = ~0;
596
597 *pr = rr;
598 *pg = gg;
599 *pb = bb;
600
601 r = *(pr + wh);
602 rr = (r >> 2) + (r >> 1);
603 if (rr > r) rr = 0;
604 g = *(pg + wh);
605 gg = (g >> 2) + (g >> 1);
606 if (gg > g) gg = 0;
607 b = *(pb + wh);
608 bb = (b >> 2) + (b >> 1);
609 if (bb > b) bb = 0;
610
611 *((pr++) + wh) = rr;
612 *((pg++) + wh) = gg;
613 *((pb++) + wh) = bb;
614 }
615
616 r = *pr;
617 rr = r + (r >> 1);
618 if (rr < r) rr = ~0;
619 g = *pg;
620 gg = g + (g >> 1);
621 if (gg < g) gg = ~0;
622 b = *pb;
623 bb = b + (b >> 1);
624 if (bb < b) bb = ~0;
625
626 *pr = rr;
627 *pg = gg;
628 *pb = bb;
629
630 r = *(pr + wh);
631 rr = (r >> 2) + (r >> 1);
632 if (rr > r) rr = 0;
633 g = *(pg + wh);
634 gg = (g >> 2) + (g >> 1);
635 if (gg > g) gg = 0;
636 b = *(pb + wh);
637 bb = (b >> 2) + (b >> 1);
638 if (bb > b) bb = 0;
639
640 *(pr + wh) = rr;
641 *(pg + wh) = gg;
642 *(pb + wh) = bb;
643
644 pr = red + width;
645 pg = green + width;
646 pb = blue + width;
647
648 while (--h) {
649 r = *pr;
650 rr = r + (r >> 1);
651 if (rr < r) rr = ~0;
652 g = *pg;
653 gg = g + (g >> 1);
654 if (gg < g) gg = ~0;
655 b = *pb;
656 bb = b + (b >> 1);
657 if (bb < b) bb = ~0;
658
659 *pr = rr;
660 *pg = gg;
661 *pb = bb;
662
663 pr += width - 1;
664 pg += width - 1;
665 pb += width - 1;
666
667 r = *pr;
668 rr = (r >> 2) + (r >> 1);
669 if (rr > r) rr = 0;
670 g = *pg;
671 gg = (g >> 2) + (g >> 1);
672 if (gg > g) gg = 0;
673 b = *pb;
674 bb = (b >> 2) + (b >> 1);
675 if (bb > b) bb = 0;
676
677 *(pr++) = rr;
678 *(pg++) = gg;
679 *(pb++) = bb;
680 }
681
682 r = *pr;
683 rr = r + (r >> 1);
684 if (rr < r) rr = ~0;
685 g = *pg;
686 gg = g + (g >> 1);
687 if (gg < g) gg = ~0;
688 b = *pb;
689 bb = b + (b >> 1);
690 if (bb < b) bb = ~0;
691
692 *pr = rr;
693 *pg = gg;
694 *pb = bb;
695
696 pr += width - 1;
697 pg += width - 1;
698 pb += width - 1;
699
700 r = *pr;
701 rr = (r >> 2) + (r >> 1);
702 if (rr > r) rr = 0;
703 g = *pg;
704 gg = (g >> 2) + (g >> 1);
705 if (gg > g) gg = 0;
706 b = *pb;
707 bb = (b >> 2) + (b >> 1);
708 if (bb > b) bb = 0;
709
710 *pr = rr;
711 *pg = gg;
712 *pb = bb;
713 }
714 }
715
716
717 void BImage::bevel2(void) {
718 if (width > 4 && height > 4) {
719 unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
720 *pg = green + width + 1, *pb = blue + width + 1;
721 unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
722
723 while (--w) {
724 r = *pr;
725 rr = r + (r >> 1);
726 if (rr < r) rr = ~0;
727 g = *pg;
728 gg = g + (g >> 1);
729 if (gg < g) gg = ~0;
730 b = *pb;
731 bb = b + (b >> 1);
732 if (bb < b) bb = ~0;
733
734 *pr = rr;
735 *pg = gg;
736 *pb = bb;
737
738 r = *(pr + wh);
739 rr = (r >> 2) + (r >> 1);
740 if (rr > r) rr = 0;
741 g = *(pg + wh);
742 gg = (g >> 2) + (g >> 1);
743 if (gg > g) gg = 0;
744 b = *(pb + wh);
745 bb = (b >> 2) + (b >> 1);
746 if (bb > b) bb = 0;
747
748 *((pr++) + wh) = rr;
749 *((pg++) + wh) = gg;
750 *((pb++) + wh) = bb;
751 }
752
753 pr = red + width;
754 pg = green + width;
755 pb = blue + width;
756
757 while (--h) {
758 r = *pr;
759 rr = r + (r >> 1);
760 if (rr < r) rr = ~0;
761 g = *pg;
762 gg = g + (g >> 1);
763 if (gg < g) gg = ~0;
764 b = *pb;
765 bb = b + (b >> 1);
766 if (bb < b) bb = ~0;
767
768 *(++pr) = rr;
769 *(++pg) = gg;
770 *(++pb) = bb;
771
772 pr += width - 3;
773 pg += width - 3;
774 pb += width - 3;
775
776 r = *pr;
777 rr = (r >> 2) + (r >> 1);
778 if (rr > r) rr = 0;
779 g = *pg;
780 gg = (g >> 2) + (g >> 1);
781 if (gg > g) gg = 0;
782 b = *pb;
783 bb = (b >> 2) + (b >> 1);
784 if (bb > b) bb = 0;
785
786 *(pr++) = rr;
787 *(pg++) = gg;
788 *(pb++) = bb;
789
790 pr++; pg++; pb++;
791 }
792 }
793 }
794
795
796 void BImage::border(const BTexture &texture) {
797 if (width < 2 || height < 2) return;
798
799 register unsigned int i;
800 int r = texture.borderColor().red(),
801 g = texture.borderColor().green(),
802 b = texture.borderColor().blue();
803
804 unsigned char *pr, *pg, *pb;
805
806 // top line
807 pr = red;
808 pg = green;
809 pb = blue;
810 for (i = 0; i < width; ++i) {
811 *pr++ = r;
812 *pg++ = g;
813 *pb++ = b;
814 }
815
816 if (height > 2) {
817 // left and right lines (pr,pg,pb are already lined up)
818 for (i = 1; i < height - 1; ++i) {
819 *pr = r;
820 *pg = g;
821 *pb = b;
822 pr += width - 1;
823 pg += width - 1;
824 pb += width - 1;
825 *pr++ = r;
826 *pg++ = g;
827 *pb++ = b;
828 }
829 }
830
831 // bottom line (pr,pg,pb are already lined up)
832 for (i = 0; i < width; ++i) {
833 *pr++ = r;
834 *pg++ = g;
835 *pb++ = b;
836 }
837 }
838
839
840 void BImage::invert(void) {
841 register unsigned int i, j, wh = (width * height) - 1;
842 unsigned char tmp;
843
844 for (i = 0, j = wh; j > i; j--, i++) {
845 tmp = *(red + j);
846 *(red + j) = *(red + i);
847 *(red + i) = tmp;
848
849 tmp = *(green + j);
850 *(green + j) = *(green + i);
851 *(green + i) = tmp;
852
853 tmp = *(blue + j);
854 *(blue + j) = *(blue + i);
855 *(blue + i) = tmp;
856 }
857 }
858
859
860 void BImage::dgradient(void) {
861 // diagonal gradient code was written by Mike Cole <mike@mydot.com>
862 // modified for interlacing by Brad Hughes
863
864 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
865 xr = (float) from.red(),
866 xg = (float) from.green(),
867 xb = (float) from.blue();
868 unsigned char *pr = red, *pg = green, *pb = blue;
869 unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable;
870
871 register unsigned int x, y;
872
873 dry = drx = (float) (to.red() - from.red());
874 dgy = dgx = (float) (to.green() - from.green());
875 dby = dbx = (float) (to.blue() - from.blue());
876
877 // Create X table
878 drx /= w;
879 dgx /= w;
880 dbx /= w;
881
882 for (x = 0; x < width; x++) {
883 *(xt++) = (unsigned char) (xr);
884 *(xt++) = (unsigned char) (xg);
885 *(xt++) = (unsigned char) (xb);
886
887 xr += drx;
888 xg += dgx;
889 xb += dbx;
890 }
891
892 // Create Y table
893 dry /= h;
894 dgy /= h;
895 dby /= h;
896
897 for (y = 0; y < height; y++) {
898 *(yt++) = ((unsigned char) yr);
899 *(yt++) = ((unsigned char) yg);
900 *(yt++) = ((unsigned char) yb);
901
902 yr += dry;
903 yg += dgy;
904 yb += dby;
905 }
906
907 // Combine tables to create gradient
908
909 if (! interlaced) {
910 // normal dgradient
911 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
912 for (xt = xtable, x = 0; x < width; x++) {
913 *(pr++) = *(xt++) + *(yt);
914 *(pg++) = *(xt++) + *(yt + 1);
915 *(pb++) = *(xt++) + *(yt + 2);
916 }
917 }
918 } else {
919 // faked interlacing effect
920 unsigned char channel, channel2;
921
922 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
923 for (xt = xtable, x = 0; x < width; x++) {
924 if (y & 1) {
925 channel = *(xt++) + *(yt);
926 channel2 = (channel >> 1) + (channel >> 2);
927 if (channel2 > channel) channel2 = 0;
928 *(pr++) = channel2;
929
930 channel = *(xt++) + *(yt + 1);
931 channel2 = (channel >> 1) + (channel >> 2);
932 if (channel2 > channel) channel2 = 0;
933 *(pg++) = channel2;
934
935 channel = *(xt++) + *(yt + 2);
936 channel2 = (channel >> 1) + (channel >> 2);
937 if (channel2 > channel) channel2 = 0;
938 *(pb++) = channel2;
939 } else {
940 channel = *(xt++) + *(yt);
941 channel2 = channel + (channel >> 3);
942 if (channel2 < channel) channel2 = ~0;
943 *(pr++) = channel2;
944
945 channel = *(xt++) + *(yt + 1);
946 channel2 = channel + (channel >> 3);
947 if (channel2 < channel) channel2 = ~0;
948 *(pg++) = channel2;
949
950 channel = *(xt++) + *(yt + 2);
951 channel2 = channel + (channel >> 3);
952 if (channel2 < channel) channel2 = ~0;
953 *(pb++) = channel2;
954 }
955 }
956 }
957 }
958 }
959
960
961 void BImage::hgradient(void) {
962 float drx, dgx, dbx,
963 xr = (float) from.red(),
964 xg = (float) from.green(),
965 xb = (float) from.blue();
966 unsigned char *pr = red, *pg = green, *pb = blue;
967
968 register unsigned int x, y;
969
970 drx = (float) (to.red() - from.red());
971 dgx = (float) (to.green() - from.green());
972 dbx = (float) (to.blue() - from.blue());
973
974 drx /= width;
975 dgx /= width;
976 dbx /= width;
977
978 if (interlaced && height > 2) {
979 // faked interlacing effect
980 unsigned char channel, channel2;
981
982 for (x = 0; x < width; x++, pr++, pg++, pb++) {
983 channel = (unsigned char) xr;
984 channel2 = (channel >> 1) + (channel >> 2);
985 if (channel2 > channel) channel2 = 0;
986 *pr = channel2;
987
988 channel = (unsigned char) xg;
989 channel2 = (channel >> 1) + (channel >> 2);
990 if (channel2 > channel) channel2 = 0;
991 *pg = channel2;
992
993 channel = (unsigned char) xb;
994 channel2 = (channel >> 1) + (channel >> 2);
995 if (channel2 > channel) channel2 = 0;
996 *pb = channel2;
997
998
999 channel = (unsigned char) xr;
1000 channel2 = channel + (channel >> 3);
1001 if (channel2 < channel) channel2 = ~0;
1002 *(pr + width) = channel2;
1003
1004 channel = (unsigned char) xg;
1005 channel2 = channel + (channel >> 3);
1006 if (channel2 < channel) channel2 = ~0;
1007 *(pg + width) = channel2;
1008
1009 channel = (unsigned char) xb;
1010 channel2 = channel + (channel >> 3);
1011 if (channel2 < channel) channel2 = ~0;
1012 *(pb + width) = channel2;
1013
1014 xr += drx;
1015 xg += dgx;
1016 xb += dbx;
1017 }
1018
1019 pr += width;
1020 pg += width;
1021 pb += width;
1022
1023 int offset;
1024
1025 for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1026 if (y & 1) offset = width; else offset = 0;
1027
1028 memcpy(pr, (red + offset), width);
1029 memcpy(pg, (green + offset), width);
1030 memcpy(pb, (blue + offset), width);
1031 }
1032 } else {
1033 // normal hgradient
1034 for (x = 0; x < width; x++) {
1035 *(pr++) = (unsigned char) (xr);
1036 *(pg++) = (unsigned char) (xg);
1037 *(pb++) = (unsigned char) (xb);
1038
1039 xr += drx;
1040 xg += dgx;
1041 xb += dbx;
1042 }
1043
1044 for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1045 memcpy(pr, red, width);
1046 memcpy(pg, green, width);
1047 memcpy(pb, blue, width);
1048 }
1049 }
1050 }
1051
1052
1053 void BImage::vgradient(void) {
1054 float dry, dgy, dby,
1055 yr = (float) from.red(),
1056 yg = (float) from.green(),
1057 yb = (float) from.blue();
1058 unsigned char *pr = red, *pg = green, *pb = blue;
1059
1060 register unsigned int y;
1061
1062 dry = (float) (to.red() - from.red());
1063 dgy = (float) (to.green() - from.green());
1064 dby = (float) (to.blue() - from.blue());
1065
1066 dry /= height;
1067 dgy /= height;
1068 dby /= height;
1069
1070 if (interlaced) {
1071 // faked interlacing effect
1072 unsigned char channel, channel2;
1073
1074 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1075 if (y & 1) {
1076 channel = (unsigned char) yr;
1077 channel2 = (channel >> 1) + (channel >> 2);
1078 if (channel2 > channel) channel2 = 0;
1079 memset(pr, channel2, width);
1080
1081 channel = (unsigned char) yg;
1082 channel2 = (channel >> 1) + (channel >> 2);
1083 if (channel2 > channel) channel2 = 0;
1084 memset(pg, channel2, width);
1085
1086 channel = (unsigned char) yb;
1087 channel2 = (channel >> 1) + (channel >> 2);
1088 if (channel2 > channel) channel2 = 0;
1089 memset(pb, channel2, width);
1090 } else {
1091 channel = (unsigned char) yr;
1092 channel2 = channel + (channel >> 3);
1093 if (channel2 < channel) channel2 = ~0;
1094 memset(pr, channel2, width);
1095
1096 channel = (unsigned char) yg;
1097 channel2 = channel + (channel >> 3);
1098 if (channel2 < channel) channel2 = ~0;
1099 memset(pg, channel2, width);
1100
1101 channel = (unsigned char) yb;
1102 channel2 = channel + (channel >> 3);
1103 if (channel2 < channel) channel2 = ~0;
1104 memset(pb, channel2, width);
1105 }
1106
1107 yr += dry;
1108 yg += dgy;
1109 yb += dby;
1110 }
1111 } else {
1112 // normal vgradient
1113 for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1114 memset(pr, (unsigned char) yr, width);
1115 memset(pg, (unsigned char) yg, width);
1116 memset(pb, (unsigned char) yb, width);
1117
1118 yr += dry;
1119 yg += dgy;
1120 yb += dby;
1121 }
1122 }
1123 }
1124
1125
1126 void BImage::pgradient(void) {
1127 // pyramid gradient - based on original dgradient, written by
1128 // Mosfet (mosfet@kde.org)
1129 // adapted from kde sources for Blackbox by Brad Hughes
1130
1131 float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1132 xr, xg, xb;
1133 int rsign, gsign, bsign;
1134 unsigned char *pr = red, *pg = green, *pb = blue;
1135 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1136 *xt = xtable, *yt = ytable;
1137
1138 register unsigned int x, y;
1139
1140 dry = drx = (float) (to.red() - from.red());
1141 dgy = dgx = (float) (to.green() - from.green());
1142 dby = dbx = (float) (to.blue() - from.blue());
1143
1144 rsign = (drx < 0) ? -1 : 1;
1145 gsign = (dgx < 0) ? -1 : 1;
1146 bsign = (dbx < 0) ? -1 : 1;
1147
1148 xr = yr = (drx / 2);
1149 xg = yg = (dgx / 2);
1150 xb = yb = (dbx / 2);
1151
1152 // Create X table
1153 drx /= width;
1154 dgx /= width;
1155 dbx /= width;
1156
1157 for (x = 0; x < width; x++) {
1158 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1159 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1160 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1161
1162 xr -= drx;
1163 xg -= dgx;
1164 xb -= dbx;
1165 }
1166
1167 // Create Y table
1168 dry /= height;
1169 dgy /= height;
1170 dby /= height;
1171
1172 for (y = 0; y < height; y++) {
1173 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1174 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1175 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1176
1177 yr -= dry;
1178 yg -= dgy;
1179 yb -= dby;
1180 }
1181
1182 // Combine tables to create gradient
1183
1184 if (! interlaced) {
1185 // normal pgradient
1186 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1187 for (xt = xtable, x = 0; x < width; x++) {
1188 *(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1189 *(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1190 *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1191 }
1192 }
1193 } else {
1194 // faked interlacing effect
1195 unsigned char channel, channel2;
1196
1197 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1198 for (xt = xtable, x = 0; x < width; x++) {
1199 if (y & 1) {
1200 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1201 channel2 = (channel >> 1) + (channel >> 2);
1202 if (channel2 > channel) channel2 = 0;
1203 *(pr++) = channel2;
1204
1205 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1206 channel2 = (channel >> 1) + (channel >> 2);
1207 if (channel2 > channel) channel2 = 0;
1208 *(pg++) = channel2;
1209
1210 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1211 channel2 = (channel >> 1) + (channel >> 2);
1212 if (channel2 > channel) channel2 = 0;
1213 *(pb++) = channel2;
1214 } else {
1215 channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1216 channel2 = channel + (channel >> 3);
1217 if (channel2 < channel) channel2 = ~0;
1218 *(pr++) = channel2;
1219
1220 channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1221 channel2 = channel + (channel >> 3);
1222 if (channel2 < channel) channel2 = ~0;
1223 *(pg++) = channel2;
1224
1225 channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1226 channel2 = channel + (channel >> 3);
1227 if (channel2 < channel) channel2 = ~0;
1228 *(pb++) = channel2;
1229 }
1230 }
1231 }
1232 }
1233 }
1234
1235
1236 void BImage::rgradient(void) {
1237 // rectangle gradient - based on original dgradient, written by
1238 // Mosfet (mosfet@kde.org)
1239 // adapted from kde sources for Blackbox by Brad Hughes
1240
1241 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1242 int rsign, gsign, bsign;
1243 unsigned char *pr = red, *pg = green, *pb = blue;
1244 unsigned int tr = to.red(), tg = to.green(), tb = to.blue(),
1245 *xt = xtable, *yt = ytable;
1246
1247 register unsigned int x, y;
1248
1249 dry = drx = (float) (to.red() - from.red());
1250 dgy = dgx = (float) (to.green() - from.green());
1251 dby = dbx = (float) (to.blue() - from.blue());
1252
1253 rsign = (drx < 0) ? -2 : 2;
1254 gsign = (dgx < 0) ? -2 : 2;
1255 bsign = (dbx < 0) ? -2 : 2;
1256
1257 xr = yr = (drx / 2);
1258 xg = yg = (dgx / 2);
1259 xb = yb = (dbx / 2);
1260
1261 // Create X table
1262 drx /= width;
1263 dgx /= width;
1264 dbx /= width;
1265
1266 for (x = 0; x < width; x++) {
1267 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1268 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1269 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1270
1271 xr -= drx;
1272 xg -= dgx;
1273 xb -= dbx;
1274 }
1275
1276 // Create Y table
1277 dry /= height;
1278 dgy /= height;
1279 dby /= height;
1280
1281 for (y = 0; y < height; y++) {
1282 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1283 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1284 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1285
1286 yr -= dry;
1287 yg -= dgy;
1288 yb -= dby;
1289 }
1290
1291 // Combine tables to create gradient
1292
1293 if (! interlaced) {
1294 // normal rgradient
1295 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1296 for (xt = xtable, x = 0; x < width; x++) {
1297 *(pr++) = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1298 *(pg++) = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1299 *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1300 }
1301 }
1302 } else {
1303 // faked interlacing effect
1304 unsigned char channel, channel2;
1305
1306 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1307 for (xt = xtable, x = 0; x < width; x++) {
1308 if (y & 1) {
1309 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1310 channel2 = (channel >> 1) + (channel >> 2);
1311 if (channel2 > channel) channel2 = 0;
1312 *(pr++) = channel2;
1313
1314 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1315 channel2 = (channel >> 1) + (channel >> 2);
1316 if (channel2 > channel) channel2 = 0;
1317 *(pg++) = channel2;
1318
1319 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1320 channel2 = (channel >> 1) + (channel >> 2);
1321 if (channel2 > channel) channel2 = 0;
1322 *(pb++) = channel2;
1323 } else {
1324 channel = (unsigned char) (tr - (rsign * max(*(xt++), *(yt))));
1325 channel2 = channel + (channel >> 3);
1326 if (channel2 < channel) channel2 = ~0;
1327 *(pr++) = channel2;
1328
1329 channel = (unsigned char) (tg - (gsign * max(*(xt++), *(yt + 1))));
1330 channel2 = channel + (channel >> 3);
1331 if (channel2 < channel) channel2 = ~0;
1332 *(pg++) = channel2;
1333
1334 channel = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2))));
1335 channel2 = channel + (channel >> 3);
1336 if (channel2 < channel) channel2 = ~0;
1337 *(pb++) = channel2;
1338 }
1339 }
1340 }
1341 }
1342 }
1343
1344
1345 void BImage::egradient(void) {
1346 // elliptic gradient - based on original dgradient, written by
1347 // Mosfet (mosfet@kde.org)
1348 // adapted from kde sources for Blackbox by Brad Hughes
1349
1350 float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1351 int rsign, gsign, bsign;
1352 unsigned char *pr = red, *pg = green, *pb = blue;
1353 unsigned int *xt = xtable, *yt = ytable,
1354 tr = (unsigned long) to.red(),
1355 tg = (unsigned long) to.green(),
1356 tb = (unsigned long) to.blue();
1357
1358 register unsigned int x, y;
1359
1360 dry = drx = (float) (to.red() - from.red());
1361 dgy = dgx = (float) (to.green() - from.green());
1362 dby = dbx = (float) (to.blue() - from.blue());
1363
1364 rsign = (drx < 0) ? -1 : 1;
1365 gsign = (dgx < 0) ? -1 : 1;
1366 bsign = (dbx < 0) ? -1 : 1;
1367
1368 xr = yr = (drx / 2);
1369 xg = yg = (dgx / 2);
1370 xb = yb = (dbx / 2);
1371
1372 // Create X table
1373 drx /= width;
1374 dgx /= width;
1375 dbx /= width;
1376
1377 for (x = 0; x < width; x++) {
1378 *(xt++) = (unsigned long) (xr * xr);
1379 *(xt++) = (unsigned long) (xg * xg);
1380 *(xt++) = (unsigned long) (xb * xb);
1381
1382 xr -= drx;
1383 xg -= dgx;
1384 xb -= dbx;
1385 }
1386
1387 // Create Y table
1388 dry /= height;
1389 dgy /= height;
1390 dby /= height;
1391
1392 for (y = 0; y < height; y++) {
1393 *(yt++) = (unsigned long) (yr * yr);
1394 *(yt++) = (unsigned long) (yg * yg);
1395 *(yt++) = (unsigned long) (yb * yb);
1396
1397 yr -= dry;
1398 yg -= dgy;
1399 yb -= dby;
1400 }
1401
1402 // Combine tables to create gradient
1403
1404 if (! interlaced) {
1405 // normal egradient
1406 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1407 for (xt = xtable, x = 0; x < width; x++) {
1408 *(pr++) = (unsigned char)
1409 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1410 *(pg++) = (unsigned char)
1411 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1412 *(pb++) = (unsigned char)
1413 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1414 }
1415 }
1416 } else {
1417 // faked interlacing effect
1418 unsigned char channel, channel2;
1419
1420 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1421 for (xt = xtable, x = 0; x < width; x++) {
1422 if (y & 1) {
1423 channel = (unsigned char)
1424 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1425 channel2 = (channel >> 1) + (channel >> 2);
1426 if (channel2 > channel) channel2 = 0;
1427 *(pr++) = channel2;
1428
1429 channel = (unsigned char)
1430 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1431 channel2 = (channel >> 1) + (channel >> 2);
1432 if (channel2 > channel) channel2 = 0;
1433 *(pg++) = channel2;
1434
1435 channel = (unsigned char)
1436 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1437 channel2 = (channel >> 1) + (channel >> 2);
1438 if (channel2 > channel) channel2 = 0;
1439 *(pb++) = channel2;
1440 } else {
1441 channel = (unsigned char)
1442 (tr - (rsign * control->getSqrt(*(xt++) + *(yt))));
1443 channel2 = channel + (channel >> 3);
1444 if (channel2 < channel) channel2 = ~0;
1445 *(pr++) = channel2;
1446
1447 channel = (unsigned char)
1448 (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1))));
1449 channel2 = channel + (channel >> 3);
1450 if (channel2 < channel) channel2 = ~0;
1451 *(pg++) = channel2;
1452
1453 channel = (unsigned char)
1454 (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2))));
1455 channel2 = channel + (channel >> 3);
1456 if (channel2 < channel) channel2 = ~0;
1457 *(pb++) = channel2;
1458 }
1459 }
1460 }
1461 }
1462 }
1463
1464
1465 void BImage::pcgradient(void) {
1466 // pipe cross gradient - based on original dgradient, written by
1467 // Mosfet (mosfet@kde.org)
1468 // adapted from kde sources for Blackbox by Brad Hughes
1469
1470 float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1471 int rsign, gsign, bsign;
1472 unsigned char *pr = red, *pg = green, *pb = blue;
1473 unsigned int *xt = xtable, *yt = ytable,
1474 tr = to.red(),
1475 tg = to.green(),
1476 tb = to.blue();
1477
1478 register unsigned int x, y;
1479
1480 dry = drx = (float) (to.red() - from.red());
1481 dgy = dgx = (float) (to.green() - from.green());
1482 dby = dbx = (float) (to.blue() - from.blue());
1483
1484 rsign = (drx < 0) ? -2 : 2;
1485 gsign = (dgx < 0) ? -2 : 2;
1486 bsign = (dbx < 0) ? -2 : 2;
1487
1488 xr = yr = (drx / 2);
1489 xg = yg = (dgx / 2);
1490 xb = yb = (dbx / 2);
1491
1492 // Create X table
1493 drx /= width;
1494 dgx /= width;
1495 dbx /= width;
1496
1497 for (x = 0; x < width; x++) {
1498 *(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1499 *(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1500 *(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1501
1502 xr -= drx;
1503 xg -= dgx;
1504 xb -= dbx;
1505 }
1506
1507 // Create Y table
1508 dry /= height;
1509 dgy /= height;
1510 dby /= height;
1511
1512 for (y = 0; y < height; y++) {
1513 *(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1514 *(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1515 *(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1516
1517 yr -= dry;
1518 yg -= dgy;
1519 yb -= dby;
1520 }
1521
1522 // Combine tables to create gradient
1523
1524 if (! interlaced) {
1525 // normal pcgradient
1526 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1527 for (xt = xtable, x = 0; x < width; x++) {
1528 *(pr++) = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1529 *(pg++) = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1530 *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1531 }
1532 }
1533 } else {
1534 // faked interlacing effect
1535 unsigned char channel, channel2;
1536
1537 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1538 for (xt = xtable, x = 0; x < width; x++) {
1539 if (y & 1) {
1540 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1541 channel2 = (channel >> 1) + (channel >> 2);
1542 if (channel2 > channel) channel2 = 0;
1543 *(pr++) = channel2;
1544
1545 channel = (unsigned char) (tg - (bsign * min(*(xt++), *(yt + 1))));
1546 channel2 = (channel >> 1) + (channel >> 2);
1547 if (channel2 > channel) channel2 = 0;
1548 *(pg++) = channel2;
1549
1550 channel = (unsigned char) (tb - (gsign * min(*(xt++), *(yt + 2))));
1551 channel2 = (channel >> 1) + (channel >> 2);
1552 if (channel2 > channel) channel2 = 0;
1553 *(pb++) = channel2;
1554 } else {
1555 channel = (unsigned char) (tr - (rsign * min(*(xt++), *(yt))));
1556 channel2 = channel + (channel >> 3);
1557 if (channel2 < channel) channel2 = ~0;
1558 *(pr++) = channel2;
1559
1560 channel = (unsigned char) (tg - (gsign * min(*(xt++), *(yt + 1))));
1561 channel2 = channel + (channel >> 3);
1562 if (channel2 < channel) channel2 = ~0;
1563 *(pg++) = channel2;
1564
1565 channel = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2))));
1566 channel2 = channel + (channel >> 3);
1567 if (channel2 < channel) channel2 = ~0;
1568 *(pb++) = channel2;
1569 }
1570 }
1571 }
1572 }
1573 }
1574
1575
1576 void BImage::cdgradient(void) {
1577 // cross diagonal gradient - based on original dgradient, written by
1578 // Mosfet (mosfet@kde.org)
1579 // adapted from kde sources for Blackbox by Brad Hughes
1580
1581 float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1582 xr = (float) from.red(),
1583 xg = (float) from.green(),
1584 xb = (float) from.blue();
1585 unsigned char *pr = red, *pg = green, *pb = blue;
1586 unsigned int w = width * 2, h = height * 2, *xt, *yt;
1587
1588 register unsigned int x, y;
1589
1590 dry = drx = (float) (to.red() - from.red());
1591 dgy = dgx = (float) (to.green() - from.green());
1592 dby = dbx = (float) (to.blue() - from.blue());
1593
1594 // Create X table
1595 drx /= w;
1596 dgx /= w;
1597 dbx /= w;
1598
1599 for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1600 *(xt--) = (unsigned char) xb;
1601 *(xt--) = (unsigned char) xg;
1602 *(xt--) = (unsigned char) xr;
1603
1604 xr += drx;
1605 xg += dgx;
1606 xb += dbx;
1607 }
1608
1609 // Create Y table
1610 dry /= h;
1611 dgy /= h;
1612 dby /= h;
1613
1614 for (yt = ytable, y = 0; y < height; y++) {
1615 *(yt++) = (unsigned char) yr;
1616 *(yt++) = (unsigned char) yg;
1617 *(yt++) = (unsigned char) yb;
1618
1619 yr += dry;
1620 yg += dgy;
1621 yb += dby;
1622 }
1623
1624 // Combine tables to create gradient
1625
1626 if (! interlaced) {
1627 // normal cdgradient
1628 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1629 for (xt = xtable, x = 0; x < width; x++) {
1630 *(pr++) = *(xt++) + *(yt);
1631 *(pg++) = *(xt++) + *(yt + 1);
1632 *(pb++) = *(xt++) + *(yt + 2);
1633 }
1634 }
1635 } else {
1636 // faked interlacing effect
1637 unsigned char channel, channel2;
1638
1639 for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1640 for (xt = xtable, x = 0; x < width; x++) {
1641 if (y & 1) {
1642 channel = *(xt++) + *(yt);
1643 channel2 = (channel >> 1) + (channel >> 2);
1644 if (channel2 > channel) channel2 = 0;
1645 *(pr++) = channel2;
1646
1647 channel = *(xt++) + *(yt + 1);
1648 channel2 = (channel >> 1) + (channel >> 2);
1649 if (channel2 > channel) channel2 = 0;
1650 *(pg++) = channel2;
1651
1652 channel = *(xt++) + *(yt + 2);
1653 channel2 = (channel >> 1) + (channel >> 2);
1654 if (channel2 > channel) channel2 = 0;
1655 *(pb++) = channel2;
1656 } else {
1657 channel = *(xt++) + *(yt);
1658 channel2 = channel + (channel >> 3);
1659 if (channel2 < channel) channel2 = ~0;
1660 *(pr++) = channel2;
1661
1662 channel = *(xt++) + *(yt + 1);
1663 channel2 = channel + (channel >> 3);
1664 if (channel2 < channel) channel2 = ~0;
1665 *(pg++) = channel2;
1666
1667 channel = *(xt++) + *(yt + 2);
1668 channel2 = channel + (channel >> 3);
1669 if (channel2 < channel) channel2 = ~0;
1670 *(pb++) = channel2;
1671 }
1672 }
1673 }
1674 }
1675 }
1676
1677 }
This page took 0.156394 seconds and 4 git commands to generate.