1
// TextureRender.cc for fluxbox
2
// Copyright (c) 2002 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
4
// from Image.cc for Blackbox - an X11 Window manager
5
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
7
// Permission is hereby granted, free of charge, to any person obtaining a
8
// copy of this software and associated documentation files (the "Software"),
9
// to deal in the Software without restriction, including without limitation
10
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
// and/or sell copies of the Software, and to permit persons to whom the
12
// Software is furnished to do so, subject to the following conditions:
14
// The above copyright notice and this permission notice shall be included in
15
// all copies or substantial portions of the Software.
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
// DEALINGS IN THE SOFTWARE.
25
// $Id: TextureRender.cc 4097 2005-09-03 14:44:07Z mathias $
27
#include "TextureRender.hh"
29
#include "ImageControl.hh"
31
#include "FbPixmap.hh"
32
#include "GContext.hh"
44
// mipspro has no new(nothrow)
45
#if defined sgi && ! defined GCC
46
#define FB_new_nothrow new
48
#define FB_new_nothrow new(std::nothrow)
53
TextureRender::TextureRender(ImageControl &imgctrl,
54
unsigned int w, unsigned int h,
55
XColor *_colors, size_t num_colors):
59
cpc(imgctrl.colorsPerChannel()),
61
red(0), green(0), blue(0),
62
width(static_cast<signed>((w > 0 ? w : 1))), height(static_cast<signed>(h > 0 ? h : 1)),
63
xtable(0), ytable(0) {
65
unsigned int texture_max_width = WidthOfScreen(ScreenOfDisplay(FbTk::App::instance()->display(), imgctrl.screenNumber())) * 2;
66
unsigned int texture_max_height = HeightOfScreen(ScreenOfDisplay(FbTk::App::instance()->display(), imgctrl.screenNumber())) * 2;
69
// clamp to "normal" size
70
if (width > texture_max_width) {
71
cerr<<"TextureRender: "<<_FBTKTEXT(Error, BigWidth, "Warning! Width > 3200 setting Width = 3200", "Image width seems too big, clamping")<<endl;
72
width = texture_max_width;
75
if (height > texture_max_height) {
76
cerr<<"TextureRender: "<<_FBTKTEXT(Error, BigHeight, "Warning! Height > 3200 setting Height = 3200", "Image height seems too big, clamping")<<endl;
77
height = texture_max_height;
81
imgctrl.colorTables(&red_table, &green_table, &blue_table,
82
&red_offset, &green_offset, &blue_offset,
83
&red_bits, &green_bits, &blue_bits);
88
TextureRender::~TextureRender() {
89
if (red != 0) delete [] red;
90
if (green != 0) delete [] green;
91
if (blue != 0) delete [] blue;
95
Pixmap TextureRender::render(const FbTk::Texture &texture) {
96
if (texture.pixmap().drawable() != 0)
97
return renderPixmap(texture);
98
else if (texture.type() & FbTk::Texture::PARENTRELATIVE)
99
return ParentRelative;
100
else if (texture.type() & FbTk::Texture::SOLID)
101
return renderSolid(texture);
102
else if (texture.type() & FbTk::Texture::GRADIENT) {
103
allocateColorTables();
104
return renderGradient(texture);
110
void TextureRender::allocateColorTables() {
114
const size_t size = width * height;
115
red = FB_new_nothrow unsigned char[size];
119
sprintf(sbuf, "%ld", (long int) size);
120
throw std::string("TextureRender::TextureRender(): " +
121
std::string(_FBTKTEXT(Error, OutOfMemoryRed, "Out of memory while allocating red buffer.", "")) + string(sbuf));
125
green = FB_new_nothrow unsigned char[size];
128
sprintf(sbuf, "%ld", (long int) size);
129
throw std::string("TextureRender::TextureRender(): " +
130
std::string(_FBTKTEXT(Error, OutOfMemoryGreen, "Out of memory while allocating green buffer.", ""))+ string(sbuf));
133
blue = FB_new_nothrow unsigned char[size];
136
sprintf(sbuf, "%ld", (long int) size);
137
throw std::string("TextureRender::TextureRender(): " +
138
std::string(_FBTKTEXT(Error, OutOfMemoryBlue, "Out of memory while allocating blue buffer.", ""))+ string(sbuf));
144
Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) {
146
FbPixmap pixmap(RootWindow(FbTk::App::instance()->display(),
147
control.screenNumber()),
151
if (pixmap.drawable() == None) {
153
cerr<<"FbTk::TextureRender::render_solid(): "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<endl;
158
FbTk::GContext gc(pixmap),
159
hgc(pixmap), lgc(pixmap);
161
gc.setForeground(texture.color());
162
gc.setFillStyle(FillSolid);
164
hgc.setForeground(texture.hiColor());
166
pixmap.fillRectangle(gc.gc(), 0, 0, width, height);
168
using namespace FbTk;
170
if (texture.type() & Texture::INTERLACED) {
171
lgc.setForeground(texture.colorTo());
172
register unsigned int i = 0;
173
for (; i < height; i += 2)
174
pixmap.drawLine(lgc.gc(), 0, i, width, i);
178
lgc.setForeground(texture.loColor());
180
if (texture.type() & Texture::BEVEL1) {
181
if (texture.type() & Texture::RAISED) {
182
pixmap.drawLine(lgc.gc(),
183
0, height - 1, width - 1, height - 1);
184
pixmap.drawLine(lgc.gc(),
185
width - 1, height - 1, width - 1, 0);
187
pixmap.drawLine(hgc.gc(),
189
pixmap.drawLine(hgc.gc(),
190
0, height - 1, 0, 0);
191
} else if (texture.type() & Texture::SUNKEN) {
192
pixmap.drawLine(hgc.gc(),
193
0, height - 1, width - 1, height - 1);
194
pixmap.drawLine(hgc.gc(),
195
width - 1, height - 1, width - 1, 0);
197
pixmap.drawLine(lgc.gc(),
199
pixmap.drawLine(lgc.gc(),
200
0, height - 1, 0, 0);
202
} else if (texture.type() & Texture::BEVEL2) {
203
if (texture.type() & Texture::RAISED) {
204
pixmap.drawLine(lgc.gc(),
205
1, height - 3, width - 3, height - 3);
206
pixmap.drawLine(lgc.gc(),
207
width - 3, height - 3, width - 3, 1);
209
pixmap.drawLine(hgc.gc(),
211
pixmap.drawLine(hgc.gc(),
212
1, height - 3, 1, 1);
213
} else if (texture.type() & Texture::SUNKEN) {
214
pixmap.drawLine(hgc.gc(),
215
1, height - 3, width - 3, height - 3);
216
pixmap.drawLine(hgc.gc(),
217
width - 3, height - 3, width - 3, 1);
219
pixmap.drawLine(lgc.gc(),
221
pixmap.drawLine(lgc.gc(),
222
1, height - 3, 1, 1);
226
return pixmap.release();
230
Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) {
232
bool inverted = false;
234
using namespace FbTk;
236
interlaced = texture.type() & Texture::INTERLACED;
238
if (texture.type() & Texture::SUNKEN) {
239
from = &(texture.colorTo());
240
to = &(texture.color());
242
if (! (texture.type() & Texture::INVERT))
245
from = &(texture.color());
246
to = &(texture.colorTo());
248
if (texture.type() & Texture::INVERT)
252
control.getGradientBuffers(width, height, &xtable, &ytable);
254
if (texture.type() & Texture::DIAGONAL)
256
else if (texture.type() & Texture::ELLIPTIC)
258
else if (texture.type() & Texture::HORIZONTAL)
260
else if (texture.type() & Texture::PYRAMID)
262
else if (texture.type() & Texture::RECTANGLE)
264
else if (texture.type() & Texture::VERTICAL)
266
else if (texture.type() & Texture::CROSSDIAGONAL)
268
else if (texture.type() & Texture::PIPECROSS)
271
if (texture.type() & Texture::BEVEL1)
273
else if (texture.type() & Texture::BEVEL2)
279
return renderPixmap();
283
Pixmap TextureRender::renderPixmap(const FbTk::Texture &src_texture) {
284
if (width != src_texture.pixmap().width() ||
285
height != src_texture.pixmap().height()) {
287
// copy src_texture's pixmap and
288
// scale/tile to fit our size
289
FbPixmap new_pm(src_texture.pixmap());
291
if ((src_texture.type() & Texture::TILED)) {
292
new_pm.tile(width,height);
294
new_pm.scale(width, height);
297
return new_pm.release();
299
// return copy of pixmap
300
return FbPixmap(src_texture.pixmap()).release();
303
XImage *TextureRender::renderXImage() {
304
Display *disp = FbTk::App::instance()->display();
307
DefaultVisual(disp, control.screenNumber()), control.depth(), ZPixmap, 0, 0,
308
width, height, 32, 0);
312
cerr<<"FbTk::TextureRender::renderXImage(): "<<_FBTKTEXT(Error, CreateXImage, "Error creating XImage", "Couldn't create an XImage")<<endl;
318
unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)];
319
register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset;
321
unsigned char *pixel_data = d, *ppixel_data = d;
324
o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
326
if (control.doDither()) {
327
unsigned char dither4[4][4] = {
334
unsigned char dither8[8][8] = {
335
{ 0, 32, 8, 40, 2, 34, 10, 42 },
336
{ 48, 16, 56, 24, 50, 18, 58, 26 },
337
{ 12, 44, 4, 36, 14, 46, 6, 38 },
338
{ 60, 28, 52, 20, 62, 30, 54, 22 },
339
{ 3, 35, 11, 43, 1, 33, 9, 41 },
340
{ 51, 19, 59, 27, 49, 17, 57, 25 },
341
{ 15, 47, 7, 39, 13, 45, 5, 37 },
342
{ 63, 31, 55, 23, 61, 29, 53, 21 } };
343
#endif // ORDEREDPSEUDO
345
switch (control.visual()->c_class) {
347
// algorithm: ordered dithering... many many thanks to rasterman
348
// (raster@rasterman.com) for telling me about this... portions of this
349
// code is based off of his code in Imlib
350
for (y = 0, offset = 0; y < height; y++) {
353
for (x = 0; x < width; x++, offset++) {
359
er = r & (red_bits - 1);
360
eg = g & (green_bits - 1);
361
eb = b & (blue_bits - 1);
367
if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++;
368
if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++;
369
if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++;
371
pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
375
*pixel_data++ = pixel;
378
case 16: // 16bpp LSB
379
*pixel_data++ = pixel;
380
*pixel_data++ = pixel >> 8;
383
case 17: // 16bpp MSB
384
*pixel_data++ = pixel >> 8;
385
*pixel_data++ = pixel;
388
case 24: // 24bpp LSB
389
*pixel_data++ = pixel;
390
*pixel_data++ = pixel >> 8;
391
*pixel_data++ = pixel >> 16;
394
case 25: // 24bpp MSB
395
*pixel_data++ = pixel >> 16;
396
*pixel_data++ = pixel >> 8;
397
*pixel_data++ = pixel;
400
case 32: // 32bpp LSB
401
*pixel_data++ = pixel;
402
*pixel_data++ = pixel >> 8;
403
*pixel_data++ = pixel >> 16;
404
*pixel_data++ = pixel >> 24;
407
case 33: // 32bpp MSB
408
*pixel_data++ = pixel >> 24;
409
*pixel_data++ = pixel >> 16;
410
*pixel_data++ = pixel >> 8;
411
*pixel_data++ = pixel;
416
pixel_data = (ppixel_data += image->bytes_per_line);
423
#ifndef ORDEREDPSEUDO
425
*rerr = new short[width + 2],
426
*gerr = new short[width + 2],
427
*berr = new short[width + 2],
428
*nrerr = new short[width + 2],
429
*ngerr = new short[width + 2],
430
*nberr = new short[width + 2];
431
int rr, gg, bb, rer, ger, ber;
432
int dd = 255 / control.colorsPerChannel();
434
for (x = 0; x < width; x++) {
435
*(rerr + x) = *(red + x);
436
*(gerr + x) = *(green + x);
437
*(berr + x) = *(blue + x);
440
*(rerr + x) = *(gerr + x) = *(berr + x) = 0;
441
#endif // ORDEREDPSEUDO
443
for (y = 0, offset = 0; y < height; y++) {
447
for (x = 0; x < width; x++, offset++) {
454
er = r & (red_bits - 1);
455
eg = g & (green_bits - 1);
456
eb = b & (blue_bits - 1);
462
if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++;
463
if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++;
464
if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++;
466
pixel = (r * cpccpc) + (g * cpc) + b;
467
*(pixel_data++) = colors[pixel].pixel;
470
pixel_data = (ppixel_data += image->bytes_per_line);
472
#else // !ORDEREDPSEUDO
473
if (y < (height - 1)) {
474
int i = offset + width;
475
for (x = 0; x < width; x++, i++) {
476
*(nrerr + x) = *(red + i);
477
*(ngerr + x) = *(green + i);
478
*(nberr + x) = *(blue + i);
481
*(nrerr + x) = *(red + (--i));
482
*(ngerr + x) = *(green + i);
483
*(nberr + x) = *(blue + i);
486
for (x = 0; x < width; x++) {
491
if (rr > 255) rr = 255; else if (rr < 0) rr = 0;
492
if (gg > 255) gg = 255; else if (gg < 0) gg = 0;
493
if (bb > 255) bb = 255; else if (bb < 0) bb = 0;
499
rer = rerr[x] - r*dd;
500
ger = gerr[x] - g*dd;
501
ber = berr[x] - b*dd;
503
pixel = (r * cpccpc) + (g * cpc) + b;
504
*pixel_data++ = colors[pixel].pixel;
519
pixel_data = (ppixel_data += image->bytes_per_line);
540
#endif // ORDEREDPSUEDO
547
for (y = 0, offset = 0; y < height; y++) {
550
for (x = 0; x < width; x++, offset++) {
554
g = *(green + offset);
555
b = *(blue + offset);
561
if ((dither[dithy][dithx] < er) && (r < (256 - 8)))
563
if ((dither[dithy][dithx] < (eg << 1)) && (g < (256 - 4)))
565
if ((dither[dithy][dithx] < eb) && (b < (256 - 8)))
568
r = *(red_table + r);
569
g = *(green_table + g);
570
b = *(blue_table + b);
572
g = ((r * 30) + (g * 59) + (b * 11)) / 100;
573
*pixel_data++ = colors[g].pixel;
576
pixel_data = (ppixel_data += image->bytes_per_line);
584
cerr<<"TextureRender::renderXImage(): "<<
585
_FBTKTEXT(Error, UnsupportedVisual, "unsupported visual", "A visual is a technical term in X")<<endl;
587
XDestroyImage(image);
590
} else { // end do dither
593
switch (control.visual()->c_class) {
596
for (y = 0, offset = 0; y < height; y++) {
597
for (x = 0; x < width; x++, offset++) {
598
r = red_table[red[offset]];
599
g = green_table[green[offset]];
600
b = blue_table[blue[offset]];
602
pixel = (r * cpccpc) + (g * cpc) + b;
603
*pixel_data++ = colors[pixel].pixel;
606
pixel_data = (ppixel_data += image->bytes_per_line);
612
for (y = 0, offset = 0; y < height; y++) {
613
for (x = 0; x < width; x++, offset++) {
614
r = red_table[red[offset]];
615
g = green_table[green[offset]];
616
b = blue_table[blue[offset]];
618
pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
622
*pixel_data++ = pixel;
625
case 16: // 16bpp LSB
626
*pixel_data++ = pixel;
627
*pixel_data++ = pixel >> 8;
630
case 17: // 16bpp MSB
631
*pixel_data++ = pixel >> 8;
632
*pixel_data++ = pixel;
635
case 24: // 24bpp LSB
636
*pixel_data++ = pixel;
637
*pixel_data++ = pixel >> 8;
638
*pixel_data++ = pixel >> 16;
641
case 25: // 24bpp MSB
642
*pixel_data++ = pixel >> 16;
643
*pixel_data++ = pixel >> 8;
644
*pixel_data++ = pixel;
647
case 32: // 32bpp LSB
648
*pixel_data++ = pixel;
649
*pixel_data++ = pixel >> 8;
650
*pixel_data++ = pixel >> 16;
651
*pixel_data++ = pixel >> 24;
654
case 33: // 32bpp MSB
655
*pixel_data++ = pixel >> 24;
656
*pixel_data++ = pixel >> 16;
657
*pixel_data++ = pixel >> 8;
658
*pixel_data++ = pixel;
663
pixel_data = (ppixel_data += image->bytes_per_line);
670
for (y = 0, offset = 0; y < height; y++) {
671
for (x = 0; x < width; x++, offset++) {
672
r = *(red_table + *(red + offset));
673
g = *(green_table + *(green + offset));
674
b = *(blue_table + *(blue + offset));
676
g = ((r * 30) + (g * 59) + (b * 11)) / 100;
677
*pixel_data++ = colors[g].pixel;
680
pixel_data = (ppixel_data += image->bytes_per_line);
687
cerr<<"TextureRender::renderXImage(): "<<
688
_FBTKTEXT(Error, UnsupportedVisual, "unsupported visual", "A visual is a technical term in X")<<endl;
690
XDestroyImage(image);
695
image->data = (char *) d;
700
Pixmap TextureRender::renderPixmap() {
701
Display *disp = FbTk::App::instance()->display();
702
FbPixmap pixmap(RootWindow(disp, control.screenNumber()),
703
width, height, control.depth());
705
if (pixmap.drawable() == None) {
707
cerr<<"FbTk::TextureRender::renderPixmap(): "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<endl;
711
XImage *image = renderXImage();
715
} else if (! image->data) {
716
XDestroyImage(image);
720
XPutImage(disp, pixmap.drawable(),
721
DefaultGC(disp, control.screenNumber()),
722
image, 0, 0, 0, 0, width, height);
724
if (image->data != 0) {
725
delete [] image->data;
729
XDestroyImage(image);
731
return pixmap.release();
735
void TextureRender::bevel1() {
736
if (! (width > 2 && height > 2))
739
unsigned char *pr = red, *pg = green, *pb = blue;
741
register unsigned char r, g, b, rr ,gg ,bb;
742
register unsigned int w = width, h = height - 1, wh = w * h;
760
rr = (r >> 2) + (r >> 1);
763
gg = (g >> 2) + (g >> 1);
766
bb = (b >> 2) + (b >> 1);
789
rr = (r >> 2) + (r >> 1);
792
gg = (g >> 2) + (g >> 1);
795
bb = (b >> 2) + (b >> 1);
826
rr = (r >> 2) + (r >> 1);
829
gg = (g >> 2) + (g >> 1);
832
bb = (b >> 2) + (b >> 1);
859
rr = (r >> 2) + (r >> 1);
862
gg = (g >> 2) + (g >> 1);
865
bb = (b >> 2) + (b >> 1);
874
void TextureRender::bevel2() {
875
if (! (width > 4 && height > 4))
878
unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1,
879
*pg = green + width + 1, *pb = blue + width + 1;
880
unsigned int w = width - 2, h = height - 1, wh = width * (height - 3);
898
rr = (r >> 2) + (r >> 1);
901
gg = (g >> 2) + (g >> 1);
904
bb = (b >> 2) + (b >> 1);
936
rr = (r >> 2) + (r >> 1);
939
gg = (g >> 2) + (g >> 1);
942
bb = (b >> 2) + (b >> 1);
954
void TextureRender::invert() {
955
register unsigned int i, j, wh = (width * height) - 1;
958
for (i = 0, j = wh; j > i; j--, i++) {
960
*(red + j) = *(red + i);
964
*(green + j) = *(green + i);
968
*(blue + j) = *(blue + i);
974
void TextureRender::dgradient() {
975
// diagonal gradient code was written by Mike Cole <mike@mydot.com>
976
// modified for interlacing by Brad Hughes
978
float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
979
xr = (float) from->red(),
980
xg = (float) from->green(),
981
xb = (float) from->blue();
982
unsigned char *pr = red, *pg = green, *pb = blue;
983
unsigned int w = width * 2, h = height * 2;
984
unsigned int *xt = xtable, *yt = ytable;
986
register unsigned int x, y;
988
dry = drx = (float) (to->red() - from->red());
989
dgy = dgx = (float) (to->green() - from->green());
990
dby = dbx = (float) (to->blue() - from->blue());
997
for (x = 0; x < width; x++) {
998
*(xt++) = (unsigned char) (xr);
999
*(xt++) = (unsigned char) (xg);
1000
*(xt++) = (unsigned char) (xb);
1012
for (y = 0; y < height; y++) {
1013
*(yt++) = ((unsigned char) yr);
1014
*(yt++) = ((unsigned char) yg);
1015
*(yt++) = ((unsigned char) yb);
1022
// Combine tables to create gradient
1029
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1030
for (xt = xtable, x = 0; x < width; x++) {
1031
*(pr++) = *(xt++) + *(yt);
1032
*(pg++) = *(xt++) + *(yt + 1);
1033
*(pb++) = *(xt++) + *(yt + 2);
1038
// faked interlacing effect
1039
unsigned char channel, channel2;
1041
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1042
for (xt = xtable, x = 0; x < width; x++) {
1044
channel = *(xt++) + *(yt);
1045
channel2 = (channel >> 1) + (channel >> 2);
1046
if (channel2 > channel) channel2 = 0;
1049
channel = *(xt++) + *(yt + 1);
1050
channel2 = (channel >> 1) + (channel >> 2);
1051
if (channel2 > channel) channel2 = 0;
1054
channel = *(xt++) + *(yt + 2);
1055
channel2 = (channel >> 1) + (channel >> 2);
1056
if (channel2 > channel) channel2 = 0;
1059
channel = *(xt++) + *(yt);
1060
channel2 = channel + (channel >> 3);
1061
if (channel2 < channel) channel2 = ~0;
1064
channel = *(xt++) + *(yt + 1);
1065
channel2 = channel + (channel >> 3);
1066
if (channel2 < channel) channel2 = ~0;
1069
channel = *(xt++) + *(yt + 2);
1070
channel2 = channel + (channel >> 3);
1071
if (channel2 < channel) channel2 = ~0;
1082
void TextureRender::hgradient() {
1083
float drx, dgx, dbx,
1084
xr = (float) from->red(),
1085
xg = (float) from->green(),
1086
xb = (float) from->blue();
1087
unsigned char *pr = red, *pg = green, *pb = blue;
1089
register unsigned int x, y;
1091
drx = (float) (to->red() - from->red());
1092
dgx = (float) (to->green() - from->green());
1093
dbx = (float) (to->blue() - from->blue());
1099
if (interlaced && height > 2) {
1100
// faked interlacing effect
1101
unsigned char channel, channel2;
1103
for (x = 0; x < width; x++, pr++, pg++, pb++) {
1104
channel = (unsigned char) xr;
1105
channel2 = (channel >> 1) + (channel >> 2);
1106
if (channel2 > channel) channel2 = 0;
1109
channel = (unsigned char) xg;
1110
channel2 = (channel >> 1) + (channel >> 2);
1111
if (channel2 > channel) channel2 = 0;
1114
channel = (unsigned char) xb;
1115
channel2 = (channel >> 1) + (channel >> 2);
1116
if (channel2 > channel) channel2 = 0;
1120
channel = (unsigned char) xr;
1121
channel2 = channel + (channel >> 3);
1122
if (channel2 < channel) channel2 = ~0;
1123
*(pr + width) = channel2;
1125
channel = (unsigned char) xg;
1126
channel2 = channel + (channel >> 3);
1127
if (channel2 < channel) channel2 = ~0;
1128
*(pg + width) = channel2;
1130
channel = (unsigned char) xb;
1131
channel2 = channel + (channel >> 3);
1132
if (channel2 < channel) channel2 = ~0;
1133
*(pb + width) = channel2;
1146
for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1147
if (y & 1) offset = width; else offset = 0;
1149
memcpy(pr, (red + offset), width);
1150
memcpy(pg, (green + offset), width);
1151
memcpy(pb, (blue + offset), width);
1156
for (x = 0; x < width; x++) {
1157
*(pr++) = (unsigned char) (xr);
1158
*(pg++) = (unsigned char) (xg);
1159
*(pb++) = (unsigned char) (xb);
1166
for (y = 1; y < height; y++, pr += width, pg += width, pb += width) {
1167
memcpy(pr, red, width);
1168
memcpy(pg, green, width);
1169
memcpy(pb, blue, width);
1177
void TextureRender::vgradient() {
1178
float dry, dgy, dby,
1179
yr = (float) from->red(),
1180
yg = (float) from->green(),
1181
yb = (float) from->blue();
1182
unsigned char *pr = red, *pg = green, *pb = blue;
1184
register unsigned int y;
1186
dry = (float) (to->red() - from->red());
1187
dgy = (float) (to->green() - from->green());
1188
dby = (float) (to->blue() - from->blue());
1195
// faked interlacing effect
1196
unsigned char channel, channel2;
1198
for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1200
channel = (unsigned char) yr;
1201
channel2 = (channel >> 1) + (channel >> 2);
1202
if (channel2 > channel) channel2 = 0;
1203
memset(pr, channel2, width);
1205
channel = (unsigned char) yg;
1206
channel2 = (channel >> 1) + (channel >> 2);
1207
if (channel2 > channel) channel2 = 0;
1208
memset(pg, channel2, width);
1210
channel = (unsigned char) yb;
1211
channel2 = (channel >> 1) + (channel >> 2);
1212
if (channel2 > channel) channel2 = 0;
1213
memset(pb, channel2, width);
1215
channel = (unsigned char) yr;
1216
channel2 = channel + (channel >> 3);
1217
if (channel2 < channel) channel2 = ~0;
1218
memset(pr, channel2, width);
1220
channel = (unsigned char) yg;
1221
channel2 = channel + (channel >> 3);
1222
if (channel2 < channel) channel2 = ~0;
1223
memset(pg, channel2, width);
1225
channel = (unsigned char) yb;
1226
channel2 = channel + (channel >> 3);
1227
if (channel2 < channel) channel2 = ~0;
1228
memset(pb, channel2, width);
1238
for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1239
memset(pr, (unsigned char) yr, width);
1240
memset(pg, (unsigned char) yg, width);
1241
memset(pb, (unsigned char) yb, width);
1253
void TextureRender::pgradient() {
1254
// pyramid gradient - based on original dgradient, written by
1255
// Mosfet (mosfet@kde.org)
1256
// adapted from kde sources for Blackbox by Brad Hughes
1258
float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1260
int rsign, gsign, bsign;
1261
unsigned char *pr = red, *pg = green, *pb = blue;
1262
unsigned int tr = to->red(), tg = to->green(), tb = to->blue();
1263
unsigned int *xt = xtable, *yt = ytable;
1265
register unsigned int x, y;
1267
dry = drx = (float) (to->red() - from->red());
1268
dgy = dgx = (float) (to->green() - from->green());
1269
dby = dbx = (float) (to->blue() - from->blue());
1271
rsign = (drx < 0) ? -1 : 1;
1272
gsign = (dgx < 0) ? -1 : 1;
1273
bsign = (dbx < 0) ? -1 : 1;
1275
xr = yr = (drx / 2);
1276
xg = yg = (dgx / 2);
1277
xb = yb = (dbx / 2);
1284
for (x = 0; x < width; x++) {
1285
*(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1286
*(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1287
*(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1299
for (y = 0; y < height; y++) {
1300
*(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1301
*(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1302
*(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1309
// Combine tables to create gradient
1315
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1316
for (xt = xtable, x = 0; x < width; x++) {
1317
*(pr++) = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1318
*(pg++) = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1319
*(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1324
// faked interlacing effect
1325
unsigned char channel, channel2;
1327
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1328
for (xt = xtable, x = 0; x < width; x++) {
1330
channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1331
channel2 = (channel >> 1) + (channel >> 2);
1332
if (channel2 > channel) channel2 = 0;
1335
channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1336
channel2 = (channel >> 1) + (channel >> 2);
1337
if (channel2 > channel) channel2 = 0;
1340
channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1341
channel2 = (channel >> 1) + (channel >> 2);
1342
if (channel2 > channel) channel2 = 0;
1345
channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1346
channel2 = channel + (channel >> 3);
1347
if (channel2 < channel) channel2 = ~0;
1350
channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1351
channel2 = channel + (channel >> 3);
1352
if (channel2 < channel) channel2 = ~0;
1355
channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1356
channel2 = channel + (channel >> 3);
1357
if (channel2 < channel) channel2 = ~0;
1367
void TextureRender::rgradient() {
1368
// rectangle gradient - based on original dgradient, written by
1369
// Mosfet (mosfet@kde.org)
1370
// adapted from kde sources for Blackbox by Brad Hughes
1372
float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1373
int rsign, gsign, bsign;
1374
unsigned char *pr = red, *pg = green, *pb = blue;
1375
unsigned int tr = to->red(), tg = to->green(), tb = to->blue();
1376
unsigned int *xt = xtable, *yt = ytable;
1378
register unsigned int x, y;
1380
dry = drx = (float) (to->red() - from->red());
1381
dgy = dgx = (float) (to->green() - from->green());
1382
dby = dbx = (float) (to->blue() - from->blue());
1384
rsign = (drx < 0) ? -2 : 2;
1385
gsign = (dgx < 0) ? -2 : 2;
1386
bsign = (dbx < 0) ? -2 : 2;
1388
xr = yr = (drx / 2);
1389
xg = yg = (dgx / 2);
1390
xb = yb = (dbx / 2);
1397
for (x = 0; x < width; x++) {
1398
*(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1399
*(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1400
*(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1412
for (y = 0; y < height; y++) {
1413
*(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1414
*(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1415
*(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1422
// Combine tables to create gradient
1428
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1429
for (xt = xtable, x = 0; x < width; x++) {
1430
*(pr++) = (unsigned char) (tr - (rsign * std::max(*(xt++), *(yt))));
1431
*(pg++) = (unsigned char) (tg - (gsign * std::max(*(xt++), *(yt + 1))));
1432
*(pb++) = (unsigned char) (tb - (bsign * std::max(*(xt++), *(yt + 2))));
1437
// faked interlacing effect
1438
unsigned char channel, channel2;
1440
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1441
for (xt = xtable, x = 0; x < width; x++) {
1443
channel = (unsigned char) (tr - (rsign * std::max(*(xt++), *(yt))));
1444
channel2 = (channel >> 1) + (channel >> 2);
1445
if (channel2 > channel) channel2 = 0;
1448
channel = (unsigned char) (tg - (gsign * std::max(*(xt++), *(yt + 1))));
1449
channel2 = (channel >> 1) + (channel >> 2);
1450
if (channel2 > channel) channel2 = 0;
1453
channel = (unsigned char) (tb - (bsign * std::max(*(xt++), *(yt + 2))));
1454
channel2 = (channel >> 1) + (channel >> 2);
1455
if (channel2 > channel) channel2 = 0;
1458
channel = (unsigned char) (tr - (rsign * std::max(*(xt++), *(yt))));
1459
channel2 = channel + (channel >> 3);
1460
if (channel2 < channel) channel2 = ~0;
1463
channel = (unsigned char) (tg - (gsign * std::max(*(xt++), *(yt + 1))));
1464
channel2 = channel + (channel >> 3);
1465
if (channel2 < channel) channel2 = ~0;
1468
channel = (unsigned char) (tb - (bsign * std::max(*(xt++), *(yt + 2))));
1469
channel2 = channel + (channel >> 3);
1470
if (channel2 < channel) channel2 = ~0;
1480
void TextureRender::egradient() {
1481
// elliptic gradient - based on original dgradient, written by
1482
// Mosfet (mosfet@kde.org)
1483
// adapted from kde sources for Blackbox by Brad Hughes
1485
float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb;
1486
int rsign, gsign, bsign;
1487
unsigned char *pr = red, *pg = green, *pb = blue;
1488
unsigned int *xt = xtable, *yt = ytable;
1489
unsigned int tr = (unsigned long) to->red(),
1490
tg = (unsigned long) to->green(),
1491
tb = (unsigned long) to->blue();
1493
register unsigned int x, y;
1495
dry = drx = (float) (to->red() - from->red());
1496
dgy = dgx = (float) (to->green() - from->green());
1497
dby = dbx = (float) (to->blue() - from->blue());
1499
rsign = (drx < 0) ? -1 : 1;
1500
gsign = (dgx < 0) ? -1 : 1;
1501
bsign = (dbx < 0) ? -1 : 1;
1503
xr = yr = (drx / 2);
1504
xg = yg = (dgx / 2);
1505
xb = yb = (dbx / 2);
1512
for (x = 0; x < width; x++) {
1513
*(xt++) = (unsigned long) (xr * xr);
1514
*(xt++) = (unsigned long) (xg * xg);
1515
*(xt++) = (unsigned long) (xb * xb);
1527
for (y = 0; y < height; y++) {
1528
*(yt++) = (unsigned long) (yr * yr);
1529
*(yt++) = (unsigned long) (yg * yg);
1530
*(yt++) = (unsigned long) (yb * yb);
1537
// Combine tables to create gradient
1540
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1541
for (xt = xtable, x = 0; x < width; x++) {
1542
*(pr++) = (unsigned char)
1543
(tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
1544
*(pg++) = (unsigned char)
1545
(tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
1546
*(pb++) = (unsigned char)
1547
(tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
1552
// faked interlacing effect
1553
unsigned char channel, channel2;
1555
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1556
for (xt = xtable, x = 0; x < width; x++) {
1558
channel = (unsigned char)
1559
(tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
1560
channel2 = (channel >> 1) + (channel >> 2);
1561
if (channel2 > channel) channel2 = 0;
1564
channel = (unsigned char)
1565
(tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
1566
channel2 = (channel >> 1) + (channel >> 2);
1567
if (channel2 > channel) channel2 = 0;
1570
channel = (unsigned char)
1571
(tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
1572
channel2 = (channel >> 1) + (channel >> 2);
1573
if (channel2 > channel) channel2 = 0;
1576
channel = (unsigned char)
1577
(tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
1578
channel2 = channel + (channel >> 3);
1579
if (channel2 < channel) channel2 = ~0;
1582
channel = (unsigned char)
1583
(tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
1584
channel2 = channel + (channel >> 3);
1585
if (channel2 < channel) channel2 = ~0;
1588
channel = (unsigned char)
1589
(tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
1590
channel2 = channel + (channel >> 3);
1591
if (channel2 < channel) channel2 = ~0;
1601
void TextureRender::pcgradient() {
1602
// pipe cross gradient - based on original dgradient, written by
1603
// Mosfet (mosfet@kde.org)
1604
// adapted from kde sources for Blackbox by Brad Hughes
1606
float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb;
1607
int rsign, gsign, bsign;
1608
unsigned char *pr = red, *pg = green, *pb = blue;
1609
unsigned int *xt = xtable, *yt = ytable;
1610
unsigned int tr = to->red(),
1614
register unsigned int x, y;
1616
dry = drx = (float) (to->red() - from->red());
1617
dgy = dgx = (float) (to->green() - from->green());
1618
dby = dbx = (float) (to->blue() - from->blue());
1620
rsign = (drx < 0) ? -2 : 2;
1621
gsign = (dgx < 0) ? -2 : 2;
1622
bsign = (dbx < 0) ? -2 : 2;
1624
xr = yr = (drx / 2);
1625
xg = yg = (dgx / 2);
1626
xb = yb = (dbx / 2);
1633
for (x = 0; x < width; x++) {
1634
*(xt++) = (unsigned char) ((xr < 0) ? -xr : xr);
1635
*(xt++) = (unsigned char) ((xg < 0) ? -xg : xg);
1636
*(xt++) = (unsigned char) ((xb < 0) ? -xb : xb);
1648
for (y = 0; y < height; y++) {
1649
*(yt++) = ((unsigned char) ((yr < 0) ? -yr : yr));
1650
*(yt++) = ((unsigned char) ((yg < 0) ? -yg : yg));
1651
*(yt++) = ((unsigned char) ((yb < 0) ? -yb : yb));
1658
// Combine tables to create gradient
1661
// normal pcgradient
1662
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1663
for (xt = xtable, x = 0; x < width; x++) {
1664
*(pr++) = (unsigned char) (tr - (rsign * std::min(*(xt++), *(yt))));
1665
*(pg++) = (unsigned char) (tg - (gsign * std::min(*(xt++), *(yt + 1))));
1666
*(pb++) = (unsigned char) (tb - (bsign * std::min(*(xt++), *(yt + 2))));
1671
// faked interlacing effect
1672
unsigned char channel, channel2;
1674
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1675
for (xt = xtable, x = 0; x < width; x++) {
1677
channel = (unsigned char) (tr - (rsign * std::min(*(xt++), *(yt))));
1678
channel2 = (channel >> 1) + (channel >> 2);
1679
if (channel2 > channel) channel2 = 0;
1682
channel = (unsigned char) (tg - (bsign * std::min(*(xt++), *(yt + 1))));
1683
channel2 = (channel >> 1) + (channel >> 2);
1684
if (channel2 > channel) channel2 = 0;
1687
channel = (unsigned char) (tb - (gsign * std::min(*(xt++), *(yt + 2))));
1688
channel2 = (channel >> 1) + (channel >> 2);
1689
if (channel2 > channel) channel2 = 0;
1692
channel = (unsigned char) (tr - (rsign * std::min(*(xt++), *(yt))));
1693
channel2 = channel + (channel >> 3);
1694
if (channel2 < channel) channel2 = ~0;
1697
channel = (unsigned char) (tg - (gsign * std::min(*(xt++), *(yt + 1))));
1698
channel2 = channel + (channel >> 3);
1699
if (channel2 < channel) channel2 = ~0;
1702
channel = (unsigned char) (tb - (bsign * std::min(*(xt++), *(yt + 2))));
1703
channel2 = channel + (channel >> 3);
1704
if (channel2 < channel) channel2 = ~0;
1714
void TextureRender::cdgradient() {
1715
// cross diagonal gradient - based on original dgradient, written by
1716
// Mosfet (mosfet@kde.org)
1717
// adapted from kde sources for Blackbox by Brad Hughes
1719
float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0,
1720
xr = (float) from->red(),
1721
xg = (float) from->green(),
1722
xb = (float) from->blue();
1723
unsigned char *pr = red, *pg = green, *pb = blue;
1724
unsigned int w = width * 2, h = height * 2, *xt, *yt;
1726
register unsigned int x, y;
1728
dry = drx = (float) (to->red() - from->red());
1729
dgy = dgx = (float) (to->green() - from->green());
1730
dby = dbx = (float) (to->blue() - from->blue());
1737
for (xt = (xtable + (width * 3) - 1), x = 0; x < width; x++) {
1738
*(xt--) = (unsigned char) xb;
1739
*(xt--) = (unsigned char) xg;
1740
*(xt--) = (unsigned char) xr;
1752
for (yt = ytable, y = 0; y < height; y++) {
1753
*(yt++) = (unsigned char) yr;
1754
*(yt++) = (unsigned char) yg;
1755
*(yt++) = (unsigned char) yb;
1762
// Combine tables to create gradient
1765
// normal cdgradient
1766
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1767
for (xt = xtable, x = 0; x < width; x++) {
1768
*(pr++) = *(xt++) + *(yt);
1769
*(pg++) = *(xt++) + *(yt + 1);
1770
*(pb++) = *(xt++) + *(yt + 2);
1775
// faked interlacing effect
1776
unsigned char channel, channel2;
1778
for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1779
for (xt = xtable, x = 0; x < width; x++) {
1781
channel = *(xt++) + *(yt);
1782
channel2 = (channel >> 1) + (channel >> 2);
1783
if (channel2 > channel) channel2 = 0;
1786
channel = *(xt++) + *(yt + 1);
1787
channel2 = (channel >> 1) + (channel >> 2);
1788
if (channel2 > channel) channel2 = 0;
1791
channel = *(xt++) + *(yt + 2);
1792
channel2 = (channel >> 1) + (channel >> 2);
1793
if (channel2 > channel) channel2 = 0;
1796
channel = *(xt++) + *(yt);
1797
channel2 = channel + (channel >> 3);
1798
if (channel2 < channel) channel2 = ~0;
1801
channel = *(xt++) + *(yt + 1);
1802
channel2 = channel + (channel >> 3);
1803
if (channel2 < channel) channel2 = ~0;
1806
channel = *(xt++) + *(yt + 2);
1807
channel2 = channel + (channel >> 3);
1808
if (channel2 < channel) channel2 = ~0;
1817
}; // end namespace FbTk