~ubuntu-branches/ubuntu/trusty/fluxbox/trusty-proposed

« back to all changes in this revision

Viewing changes to src/FbTk/TextureRender.cc

  • Committer: Bazaar Package Importer
  • Author(s): Dmitry E. Oboukhov
  • Date: 2008-07-01 10:38:14 UTC
  • mfrom: (2.1.12 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080701103814-khx2b6il152x9p93
Tags: 1.0.0+deb1-8
* x-dev has been removed from build-depends (out-of-date package).
* Standards-Version bumped to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// TextureRender.cc for fluxbox
2
 
// Copyright (c) 2002 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
3
 
//
4
 
// from Image.cc for Blackbox - an X11 Window manager
5
 
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
6
 
//
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:
13
 
//
14
 
// The above copyright notice and this permission notice shall be included in
15
 
// all copies or substantial portions of the Software.
16
 
//
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.
24
 
 
25
 
// $Id: TextureRender.cc 4097 2005-09-03 14:44:07Z mathias $
26
 
 
27
 
#include "TextureRender.hh"
28
 
 
29
 
#include "ImageControl.hh"
30
 
#include "App.hh"
31
 
#include "FbPixmap.hh"
32
 
#include "GContext.hh"
33
 
#include "I18n.hh"
34
 
 
35
 
#include <iostream>
36
 
#include <string>
37
 
#ifdef HAVE_CSTDIO
38
 
  #include <cstdio>
39
 
#else
40
 
  #include <stdio.h>
41
 
#endif
42
 
using namespace std;
43
 
 
44
 
// mipspro has no new(nothrow)
45
 
#if defined sgi && ! defined GCC
46
 
#define FB_new_nothrow new
47
 
#else
48
 
#define FB_new_nothrow new(std::nothrow)
49
 
#endif
50
 
 
51
 
namespace FbTk {
52
 
 
53
 
TextureRender::TextureRender(ImageControl &imgctrl, 
54
 
                             unsigned int w, unsigned int h, 
55
 
                             XColor *_colors, size_t num_colors):
56
 
    control(imgctrl),
57
 
    colors(_colors),
58
 
    ncolors(ncolors),
59
 
    cpc(imgctrl.colorsPerChannel()),
60
 
    cpccpc(cpc * cpc),
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) {
64
 
 
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;
67
 
    
68
 
    _FB_USES_NLS;
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;
73
 
    }
74
 
 
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;
78
 
    }
79
 
 
80
 
 
81
 
    imgctrl.colorTables(&red_table, &green_table, &blue_table,
82
 
                        &red_offset, &green_offset, &blue_offset,
83
 
                        &red_bits, &green_bits, &blue_bits);
84
 
        
85
 
}
86
 
 
87
 
 
88
 
TextureRender::~TextureRender() {
89
 
    if (red != 0) delete [] red;
90
 
    if (green != 0) delete [] green;
91
 
    if (blue != 0) delete [] blue;      
92
 
}
93
 
 
94
 
 
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);
105
 
    }
106
 
 
107
 
    return None;
108
 
}
109
 
 
110
 
void TextureRender::allocateColorTables() {
111
 
 
112
 
    _FB_USES_NLS;
113
 
 
114
 
    const size_t size = width * height;
115
 
    red = FB_new_nothrow unsigned char[size];
116
 
 
117
 
    if (red == 0) {
118
 
        char sbuf[128];
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));
122
 
    }
123
 
 
124
 
 
125
 
    green = FB_new_nothrow unsigned char[size];
126
 
    if (green == 0) {
127
 
        char sbuf[128];
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));
131
 
    }
132
 
 
133
 
    blue = FB_new_nothrow unsigned char[size];
134
 
    if (blue == 0) {
135
 
        char sbuf[128];
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));
139
 
    }
140
 
 
141
 
 
142
 
}
143
 
 
144
 
Pixmap TextureRender::renderSolid(const FbTk::Texture &texture) {
145
 
 
146
 
    FbPixmap pixmap(RootWindow(FbTk::App::instance()->display(),
147
 
                               control.screenNumber()), 
148
 
                    width, height,
149
 
                    control.depth());
150
 
 
151
 
    if (pixmap.drawable() == None) {
152
 
        _FB_USES_NLS;
153
 
        cerr<<"FbTk::TextureRender::render_solid(): "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<endl;
154
 
        return None;
155
 
    }
156
 
 
157
 
 
158
 
    FbTk::GContext gc(pixmap), 
159
 
        hgc(pixmap), lgc(pixmap);
160
 
 
161
 
    gc.setForeground(texture.color());
162
 
    gc.setFillStyle(FillSolid);
163
 
 
164
 
    hgc.setForeground(texture.hiColor());
165
 
 
166
 
    pixmap.fillRectangle(gc.gc(), 0, 0, width, height);
167
 
        
168
 
    using namespace FbTk;
169
 
        
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);
175
 
 
176
 
    }
177
 
 
178
 
    lgc.setForeground(texture.loColor());
179
 
 
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);
186
 
 
187
 
            pixmap.drawLine(hgc.gc(),
188
 
                            0, 0, width - 1, 0);
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);
196
 
 
197
 
            pixmap.drawLine(lgc.gc(),
198
 
                            0, 0, width - 1, 0);
199
 
            pixmap.drawLine(lgc.gc(),
200
 
                            0, height - 1, 0, 0);
201
 
        }
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);
208
 
 
209
 
            pixmap.drawLine(hgc.gc(),
210
 
                            1, 1, width - 3, 1);
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);
218
 
 
219
 
            pixmap.drawLine(lgc.gc(),
220
 
                            1, 1, width - 3, 1);
221
 
            pixmap.drawLine(lgc.gc(),
222
 
                            1, height - 3, 1, 1);
223
 
        }
224
 
    }
225
 
 
226
 
    return pixmap.release();
227
 
}
228
 
 
229
 
 
230
 
Pixmap TextureRender::renderGradient(const FbTk::Texture &texture) {
231
 
 
232
 
    bool inverted = false;
233
 
 
234
 
    using namespace FbTk;
235
 
 
236
 
    interlaced = texture.type() & Texture::INTERLACED;
237
 
 
238
 
    if (texture.type() & Texture::SUNKEN) {
239
 
        from = &(texture.colorTo());
240
 
        to = &(texture.color());
241
 
 
242
 
        if (! (texture.type() & Texture::INVERT)) 
243
 
            inverted = true;
244
 
    } else {
245
 
        from = &(texture.color());
246
 
        to = &(texture.colorTo());
247
 
 
248
 
        if (texture.type() & Texture::INVERT) 
249
 
            inverted = true;
250
 
    }
251
 
 
252
 
    control.getGradientBuffers(width, height, &xtable, &ytable);
253
 
 
254
 
    if (texture.type() & Texture::DIAGONAL) 
255
 
        dgradient();
256
 
    else if (texture.type() & Texture::ELLIPTIC) 
257
 
        egradient();
258
 
    else if (texture.type() & Texture::HORIZONTAL) 
259
 
        hgradient();
260
 
    else if (texture.type() & Texture::PYRAMID) 
261
 
        pgradient();
262
 
    else if (texture.type() & Texture::RECTANGLE) 
263
 
        rgradient();
264
 
    else if (texture.type() & Texture::VERTICAL) 
265
 
        vgradient();
266
 
    else if (texture.type() & Texture::CROSSDIAGONAL) 
267
 
        cdgradient();
268
 
    else if (texture.type() & Texture::PIPECROSS) 
269
 
        pcgradient();
270
 
 
271
 
    if (texture.type() & Texture::BEVEL1)
272
 
        bevel1();
273
 
    else if (texture.type() & Texture::BEVEL2)
274
 
        bevel2();
275
 
 
276
 
    if (inverted)
277
 
        invert();
278
 
 
279
 
    return renderPixmap();
280
 
 
281
 
}
282
 
 
283
 
Pixmap TextureRender::renderPixmap(const FbTk::Texture &src_texture) {
284
 
    if (width != src_texture.pixmap().width() ||
285
 
        height != src_texture.pixmap().height()) {
286
 
 
287
 
        // copy src_texture's pixmap and 
288
 
        // scale/tile to fit our size
289
 
        FbPixmap new_pm(src_texture.pixmap());
290
 
 
291
 
        if ((src_texture.type() & Texture::TILED)) {
292
 
            new_pm.tile(width,height);
293
 
        } else {
294
 
            new_pm.scale(width, height);
295
 
        }
296
 
 
297
 
        return new_pm.release();
298
 
    }
299
 
    // return copy of pixmap
300
 
    return FbPixmap(src_texture.pixmap()).release();
301
 
}
302
 
 
303
 
XImage *TextureRender::renderXImage() {
304
 
    Display *disp = FbTk::App::instance()->display();
305
 
    XImage *image =
306
 
        XCreateImage(disp,
307
 
                     DefaultVisual(disp, control.screenNumber()), control.depth(), ZPixmap, 0, 0,
308
 
                     width, height, 32, 0);
309
 
 
310
 
    if (! image) {
311
 
        _FB_USES_NLS;
312
 
        cerr<<"FbTk::TextureRender::renderXImage(): "<<_FBTKTEXT(Error, CreateXImage, "Error creating XImage", "Couldn't create an XImage")<<endl;
313
 
        return 0;
314
 
    }
315
 
 
316
 
    image->data = 0;
317
 
 
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;
320
 
 
321
 
    unsigned char *pixel_data = d, *ppixel_data = d;
322
 
    unsigned long pixel;
323
 
 
324
 
    o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0);
325
 
 
326
 
    if (control.doDither()) {
327
 
        unsigned char dither4[4][4] = { 
328
 
            {0, 4, 1, 5},
329
 
            {6, 2, 7, 3},
330
 
            {1, 5, 0, 4},
331
 
            {7, 3, 6, 2} };
332
 
 
333
 
#ifdef ORDEREDPSEUDO
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
344
 
 
345
 
        switch (control.visual()->c_class) {
346
 
        case TrueColor:
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++) {
351
 
                dithy = y & 0x3;
352
 
 
353
 
                for (x = 0; x < width; x++, offset++) {
354
 
                    dithx = x & 0x3;
355
 
                    r = red[offset];
356
 
                    g = green[offset];
357
 
                    b = blue[offset];
358
 
 
359
 
                    er = r & (red_bits - 1);
360
 
                    eg = g & (green_bits - 1);
361
 
                    eb = b & (blue_bits - 1);
362
 
 
363
 
                    r = red_table[r];
364
 
                    g = green_table[g];
365
 
                    b = blue_table[b];
366
 
 
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++;
370
 
 
371
 
                    pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
372
 
 
373
 
                    switch (o) {
374
 
                    case        8: //   8bpp
375
 
                        *pixel_data++ = pixel;
376
 
                        break;
377
 
 
378
 
                    case 16: // 16bpp LSB
379
 
                        *pixel_data++ = pixel;
380
 
                        *pixel_data++ = pixel >> 8;
381
 
                        break;
382
 
 
383
 
                    case 17: // 16bpp MSB
384
 
                        *pixel_data++ = pixel >> 8;
385
 
                        *pixel_data++ = pixel;
386
 
                        break;
387
 
 
388
 
                    case 24: // 24bpp LSB
389
 
                        *pixel_data++ = pixel;
390
 
                        *pixel_data++ = pixel >> 8;
391
 
                        *pixel_data++ = pixel >> 16;
392
 
                        break;
393
 
 
394
 
                    case 25: // 24bpp MSB
395
 
                        *pixel_data++ = pixel >> 16;
396
 
                        *pixel_data++ = pixel >> 8;
397
 
                        *pixel_data++ = pixel;
398
 
                        break;
399
 
 
400
 
                    case 32: // 32bpp LSB
401
 
                        *pixel_data++ = pixel;
402
 
                        *pixel_data++ = pixel >> 8;
403
 
                        *pixel_data++ = pixel >> 16;
404
 
                        *pixel_data++ = pixel >> 24;
405
 
                        break;
406
 
 
407
 
                    case 33: // 32bpp MSB
408
 
                        *pixel_data++ = pixel >> 24;
409
 
                        *pixel_data++ = pixel >> 16;
410
 
                        *pixel_data++ = pixel >> 8;
411
 
                        *pixel_data++ = pixel;
412
 
                        break;
413
 
                    }
414
 
                }
415
 
 
416
 
                pixel_data = (ppixel_data += image->bytes_per_line);
417
 
            }
418
 
 
419
 
            break;
420
 
 
421
 
        case StaticColor:
422
 
        case PseudoColor: {
423
 
#ifndef  ORDEREDPSEUDO
424
 
            short *terr,
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();
433
 
 
434
 
            for (x = 0; x < width; x++) {
435
 
                *(rerr + x) = *(red + x);
436
 
                *(gerr + x) = *(green + x);
437
 
                *(berr + x) = *(blue + x);
438
 
            }
439
 
 
440
 
            *(rerr + x) = *(gerr + x) = *(berr + x) = 0;
441
 
#endif // ORDEREDPSEUDO
442
 
 
443
 
            for (y = 0, offset = 0; y < height; y++) {
444
 
#ifdef          ORDEREDPSEUDO
445
 
                dithy = y & 7;
446
 
 
447
 
                for (x = 0; x < width; x++, offset++) {
448
 
                    dithx = x & 7;
449
 
 
450
 
                    r = red[offset];
451
 
                    g = green[offset];
452
 
                    b = blue[offset];
453
 
 
454
 
                    er = r & (red_bits - 1);
455
 
                    eg = g & (green_bits - 1);
456
 
                    eb = b & (blue_bits - 1);
457
 
 
458
 
                    r = red_table[r];
459
 
                    g = green_table[g];
460
 
                    b = blue_table[b];
461
 
 
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++;
465
 
 
466
 
                    pixel = (r * cpccpc) + (g * cpc) + b;
467
 
                    *(pixel_data++) = colors[pixel].pixel;
468
 
                }
469
 
 
470
 
                pixel_data = (ppixel_data += image->bytes_per_line);
471
 
            }
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);
479
 
                }
480
 
 
481
 
                *(nrerr + x) = *(red + (--i));
482
 
                *(ngerr + x) = *(green + i);
483
 
                *(nberr + x) = *(blue + i);
484
 
            }
485
 
 
486
 
            for (x = 0; x < width; x++) {
487
 
                rr = rerr[x];
488
 
                gg = gerr[x];
489
 
                bb = berr[x];
490
 
 
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;
494
 
 
495
 
                r = red_table[rr];
496
 
                g = green_table[gg];
497
 
                b = blue_table[bb];
498
 
 
499
 
                rer = rerr[x] - r*dd;
500
 
                ger = gerr[x] - g*dd;
501
 
                ber = berr[x] - b*dd;
502
 
 
503
 
                pixel = (r * cpccpc) + (g * cpc) + b;
504
 
                *pixel_data++ = colors[pixel].pixel;
505
 
 
506
 
                r = rer >> 1;
507
 
                g = ger >> 1;
508
 
                b = ber >> 1;
509
 
                rerr[x+1] += r;
510
 
                gerr[x+1] += g;
511
 
                berr[x+1] += b;
512
 
                nrerr[x] += r;
513
 
                ngerr[x] += g;
514
 
                nberr[x] += b;
515
 
            }
516
 
 
517
 
            offset += width;
518
 
 
519
 
            pixel_data = (ppixel_data += image->bytes_per_line);
520
 
 
521
 
            terr = rerr;
522
 
            rerr = nrerr;
523
 
            nrerr = terr;
524
 
 
525
 
            terr = gerr;
526
 
            gerr = ngerr;
527
 
            ngerr = terr;
528
 
 
529
 
            terr = berr;
530
 
            berr = nberr;
531
 
            nberr = terr;
532
 
        }
533
 
 
534
 
            delete [] rerr;
535
 
            delete [] gerr;
536
 
            delete [] berr;
537
 
            delete [] nrerr;
538
 
            delete [] ngerr;
539
 
            delete [] nberr;
540
 
#endif // ORDEREDPSUEDO
541
 
 
542
 
        } break;
543
 
 
544
 
        /*
545
 
          case StaticGray:
546
 
          case GrayScale:
547
 
          for (y = 0, offset = 0; y < height; y++) {
548
 
          dithy = y & 0x3;
549
 
 
550
 
          for (x = 0; x < width; x++, offset++) {
551
 
          dithx = x & 0x3;
552
 
 
553
 
          r = *(red + offset);
554
 
          g = *(green + offset);
555
 
          b = *(blue + offset);
556
 
 
557
 
          er = r & 0x7;
558
 
          eg = g & 0x7;
559
 
          eb = b & 0x7;
560
 
 
561
 
          if ((dither[dithy][dithx] < er) && (r < (256 - 8)))
562
 
          r += 8;
563
 
          if ((dither[dithy][dithx] < (eg << 1)) && (g < (256 - 4)))
564
 
          g += 4;
565
 
          if ((dither[dithy][dithx] < eb) && (b < (256 - 8)))
566
 
          b += 8;
567
 
 
568
 
          r = *(red_table + r);
569
 
          g = *(green_table + g);
570
 
          b = *(blue_table + b);
571
 
 
572
 
          g = ((r * 30) + (g * 59) + (b * 11)) / 100;
573
 
          *pixel_data++ = colors[g].pixel;
574
 
          }
575
 
 
576
 
          pixel_data = (ppixel_data += image->bytes_per_line);
577
 
          }
578
 
 
579
 
          break;
580
 
        */
581
 
 
582
 
    default:
583
 
        _FB_USES_NLS;
584
 
        cerr<<"TextureRender::renderXImage(): "<<
585
 
            _FBTKTEXT(Error, UnsupportedVisual, "unsupported visual", "A visual is a technical term in X")<<endl;
586
 
        delete [] d;
587
 
        XDestroyImage(image);
588
 
        return (XImage *) 0;
589
 
    }
590
 
} else { // end do dither
591
 
 
592
 
    // no dither:
593
 
    switch (control.visual()->c_class) {
594
 
    case StaticColor:
595
 
    case PseudoColor:
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]];
601
 
 
602
 
                pixel = (r * cpccpc) + (g * cpc) + b;
603
 
                *pixel_data++ = colors[pixel].pixel;
604
 
            }
605
 
 
606
 
            pixel_data = (ppixel_data += image->bytes_per_line);
607
 
        }
608
 
 
609
 
        break;
610
 
 
611
 
    case TrueColor:
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]];
617
 
 
618
 
                pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset);
619
 
 
620
 
                switch (o) {
621
 
                case    8: //   8bpp
622
 
                    *pixel_data++ = pixel;
623
 
                    break;
624
 
 
625
 
                case 16: // 16bpp LSB
626
 
                    *pixel_data++ = pixel;
627
 
                    *pixel_data++ = pixel >> 8;
628
 
                    break;
629
 
 
630
 
                case 17: // 16bpp MSB
631
 
                    *pixel_data++ = pixel >> 8;
632
 
                    *pixel_data++ = pixel;
633
 
                    break;
634
 
 
635
 
                case 24: // 24bpp LSB
636
 
                    *pixel_data++ = pixel;
637
 
                    *pixel_data++ = pixel >> 8;
638
 
                    *pixel_data++ = pixel >> 16;
639
 
                    break;
640
 
 
641
 
                case 25: // 24bpp MSB
642
 
                    *pixel_data++ = pixel >> 16;
643
 
                    *pixel_data++ = pixel >> 8;
644
 
                    *pixel_data++ = pixel;
645
 
                    break;
646
 
 
647
 
                case 32: // 32bpp LSB
648
 
                    *pixel_data++ = pixel;
649
 
                    *pixel_data++ = pixel >> 8;
650
 
                    *pixel_data++ = pixel >> 16;
651
 
                    *pixel_data++ = pixel >> 24;
652
 
                    break;
653
 
 
654
 
                case 33: // 32bpp MSB
655
 
                    *pixel_data++ = pixel >> 24;
656
 
                    *pixel_data++ = pixel >> 16;
657
 
                    *pixel_data++ = pixel >> 8;
658
 
                    *pixel_data++ = pixel;
659
 
                    break;
660
 
                }
661
 
            }
662
 
 
663
 
            pixel_data = (ppixel_data += image->bytes_per_line);
664
 
        }
665
 
 
666
 
        break;
667
 
 
668
 
    case StaticGray:
669
 
    case GrayScale:
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));
675
 
 
676
 
                g = ((r * 30) + (g * 59) + (b * 11)) / 100;
677
 
                *pixel_data++ = colors[g].pixel;
678
 
            }
679
 
 
680
 
            pixel_data = (ppixel_data += image->bytes_per_line);
681
 
        }
682
 
 
683
 
        break;
684
 
 
685
 
    default:
686
 
        _FB_USES_NLS;
687
 
        cerr<<"TextureRender::renderXImage(): "<<
688
 
            _FBTKTEXT(Error, UnsupportedVisual, "unsupported visual", "A visual is a technical term in X")<<endl;
689
 
        delete [] d;
690
 
        XDestroyImage(image);
691
 
        return (XImage *) 0;
692
 
    }
693
 
}
694
 
 
695
 
image->data = (char *) d;
696
 
return image;
697
 
}
698
 
 
699
 
 
700
 
Pixmap TextureRender::renderPixmap() {
701
 
    Display *disp = FbTk::App::instance()->display();
702
 
    FbPixmap pixmap(RootWindow(disp, control.screenNumber()), 
703
 
                    width, height, control.depth());
704
 
 
705
 
    if (pixmap.drawable() == None) {
706
 
        _FB_USES_NLS;
707
 
        cerr<<"FbTk::TextureRender::renderPixmap(): "<<_FBTKTEXT(Error, CreatePixmap, "Error creating pixmap", "Couldn't create a pixmap - image - for some reason")<<endl;
708
 
        return None;
709
 
    }
710
 
 
711
 
    XImage *image = renderXImage();
712
 
 
713
 
    if (! image) {
714
 
        return None;
715
 
    } else if (! image->data) {
716
 
        XDestroyImage(image);
717
 
        return None;
718
 
    }
719
 
 
720
 
    XPutImage(disp, pixmap.drawable(),
721
 
              DefaultGC(disp, control.screenNumber()),
722
 
              image, 0, 0, 0, 0, width, height);
723
 
 
724
 
    if (image->data != 0) {
725
 
        delete [] image->data;
726
 
        image->data = 0;
727
 
    }
728
 
 
729
 
    XDestroyImage(image);
730
 
 
731
 
    return pixmap.release();
732
 
}
733
 
 
734
 
 
735
 
void TextureRender::bevel1() {
736
 
    if (! (width > 2 && height > 2))
737
 
        return;
738
 
 
739
 
    unsigned char *pr = red, *pg = green, *pb = blue;
740
 
 
741
 
    register unsigned char r, g, b, rr ,gg ,bb;
742
 
    register unsigned int w = width, h = height - 1, wh = w * h;
743
 
 
744
 
    while (--w) {
745
 
        r = *pr;
746
 
        rr = r + (r >> 1);
747
 
        if (rr < r) rr = ~0;
748
 
        g = *pg;
749
 
        gg = g + (g >> 1);
750
 
        if (gg < g) gg = ~0;
751
 
        b = *pb;
752
 
        bb = b + (b >> 1);
753
 
        if (bb < b) bb = ~0;
754
 
 
755
 
        *pr = rr;
756
 
        *pg = gg;
757
 
        *pb = bb;
758
 
 
759
 
        r = *(pr + wh);
760
 
        rr = (r >> 2) + (r >> 1);
761
 
        if (rr > r) rr = 0;
762
 
        g = *(pg + wh);
763
 
        gg = (g >> 2) + (g >> 1);
764
 
        if (gg > g) gg = 0;
765
 
        b = *(pb + wh);
766
 
        bb = (b >> 2) + (b >> 1);
767
 
        if (bb > b) bb = 0;
768
 
 
769
 
        *((pr++) + wh) = rr;
770
 
        *((pg++) + wh) = gg;
771
 
        *((pb++) + wh) = bb;
772
 
    }
773
 
 
774
 
    r = *pr;
775
 
    rr = r + (r >> 1);
776
 
    if (rr < r) rr = ~0;
777
 
    g = *pg;
778
 
    gg = g + (g >> 1);
779
 
    if (gg < g) gg = ~0;
780
 
    b = *pb;
781
 
    bb = b + (b >> 1);
782
 
    if (bb < b) bb = ~0;
783
 
 
784
 
    *pr = rr;
785
 
    *pg = gg;
786
 
    *pb = bb;
787
 
 
788
 
    r = *(pr + wh);
789
 
    rr = (r >> 2) + (r >> 1);
790
 
    if (rr > r) rr = 0;
791
 
    g = *(pg + wh);
792
 
    gg = (g >> 2) + (g >> 1);
793
 
    if (gg > g) gg = 0;
794
 
    b = *(pb + wh);
795
 
    bb = (b >> 2) + (b >> 1);
796
 
    if (bb > b) bb = 0;
797
 
 
798
 
    *(pr + wh) = rr;
799
 
    *(pg + wh) = gg;
800
 
    *(pb + wh) = bb;
801
 
 
802
 
    pr = red + width;
803
 
    pg = green + width;
804
 
    pb = blue + width;
805
 
 
806
 
    while (--h) {
807
 
        r = *pr;
808
 
        rr = r + (r >> 1);
809
 
        if (rr < r) rr = ~0;
810
 
        g = *pg;
811
 
        gg = g + (g >> 1);
812
 
        if (gg < g) gg = ~0;
813
 
        b = *pb;
814
 
        bb = b + (b >> 1);
815
 
        if (bb < b) bb = ~0;
816
 
 
817
 
        *pr = rr;
818
 
        *pg = gg;
819
 
        *pb = bb;
820
 
 
821
 
        pr += width - 1;
822
 
        pg += width - 1;
823
 
        pb += width - 1;
824
 
 
825
 
        r = *pr;
826
 
        rr = (r >> 2) + (r >> 1);
827
 
        if (rr > r) rr = 0;
828
 
        g = *pg;
829
 
        gg = (g >> 2) + (g >> 1);
830
 
        if (gg > g) gg = 0;
831
 
        b = *pb;
832
 
        bb = (b >> 2) + (b >> 1);
833
 
        if (bb > b) bb = 0;
834
 
 
835
 
        *(pr++) = rr;
836
 
        *(pg++) = gg;
837
 
        *(pb++) = bb;
838
 
    }
839
 
 
840
 
    r = *pr;
841
 
    rr = r + (r >> 1);
842
 
    if (rr < r) rr = ~0;
843
 
    g = *pg;
844
 
    gg = g + (g >> 1);
845
 
    if (gg < g) gg = ~0;
846
 
    b = *pb;
847
 
    bb = b + (b >> 1);
848
 
    if (bb < b) bb = ~0;
849
 
 
850
 
    *pr = rr;
851
 
    *pg = gg;
852
 
    *pb = bb;
853
 
 
854
 
    pr += width - 1;
855
 
    pg += width - 1;
856
 
    pb += width - 1;
857
 
 
858
 
    r = *pr;
859
 
    rr = (r >> 2) + (r >> 1);
860
 
    if (rr > r) rr = 0;
861
 
    g = *pg;
862
 
    gg = (g >> 2) + (g >> 1);
863
 
    if (gg > g) gg = 0;
864
 
    b = *pb;
865
 
    bb = (b >> 2) + (b >> 1);
866
 
    if (bb > b) bb = 0;
867
 
 
868
 
    *pr = rr;
869
 
    *pg = gg;
870
 
    *pb = bb;
871
 
}
872
 
 
873
 
 
874
 
void TextureRender::bevel2() {
875
 
    if (! (width > 4 && height > 4))
876
 
        return;
877
 
 
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);
881
 
 
882
 
    while (--w) {
883
 
        r = *pr;
884
 
        rr = r + (r >> 1);
885
 
        if (rr < r) rr = ~0;
886
 
        g = *pg;
887
 
        gg = g + (g >> 1);
888
 
        if (gg < g) gg = ~0;
889
 
        b = *pb;
890
 
        bb = b + (b >> 1);
891
 
        if (bb < b) bb = ~0;
892
 
 
893
 
        *pr = rr;
894
 
        *pg = gg;
895
 
        *pb = bb;
896
 
 
897
 
        r = *(pr + wh);
898
 
        rr = (r >> 2) + (r >> 1);
899
 
        if (rr > r) rr = 0;
900
 
        g = *(pg + wh);
901
 
        gg = (g >> 2) + (g >> 1);
902
 
        if (gg > g) gg = 0;
903
 
        b = *(pb + wh);
904
 
        bb = (b >> 2) + (b >> 1);
905
 
        if (bb > b) bb = 0;
906
 
 
907
 
        *((pr++) + wh) = rr;
908
 
        *((pg++) + wh) = gg;
909
 
        *((pb++) + wh) = bb;
910
 
    }
911
 
 
912
 
    pr = red + width;
913
 
    pg = green + width;
914
 
    pb = blue + width;
915
 
 
916
 
    while (--h) {
917
 
        r = *pr;
918
 
        rr = r + (r >> 1);
919
 
        if (rr < r) rr = ~0;
920
 
        g = *pg;
921
 
        gg = g + (g >> 1);
922
 
        if (gg < g) gg = ~0;
923
 
        b = *pb;
924
 
        bb = b + (b >> 1);
925
 
        if (bb < b) bb = ~0;
926
 
 
927
 
        *(++pr) = rr;
928
 
        *(++pg) = gg;
929
 
        *(++pb) = bb;
930
 
 
931
 
        pr += width - 3;
932
 
        pg += width - 3;
933
 
        pb += width - 3;
934
 
 
935
 
        r = *pr;
936
 
        rr = (r >> 2) + (r >> 1);
937
 
        if (rr > r) rr = 0;
938
 
        g = *pg;
939
 
        gg = (g >> 2) + (g >> 1);
940
 
        if (gg > g) gg = 0;
941
 
        b = *pb;
942
 
        bb = (b >> 2) + (b >> 1);
943
 
        if (bb > b) bb = 0;
944
 
 
945
 
        *(pr++) = rr;
946
 
        *(pg++) = gg;
947
 
        *(pb++) = bb;
948
 
 
949
 
        pr++; pg++; pb++;
950
 
    }
951
 
}
952
 
 
953
 
 
954
 
void TextureRender::invert() {
955
 
    register unsigned int i, j, wh = (width * height) - 1;
956
 
    unsigned char tmp;
957
 
 
958
 
    for (i = 0, j = wh; j > i; j--, i++) {
959
 
        tmp = *(red + j);
960
 
        *(red + j) = *(red + i);
961
 
        *(red + i) = tmp;
962
 
 
963
 
        tmp = *(green + j);
964
 
        *(green + j) = *(green + i);
965
 
        *(green + i) = tmp;
966
 
 
967
 
        tmp = *(blue + j);
968
 
        *(blue + j) = *(blue + i);
969
 
        *(blue + i) = tmp;
970
 
    }
971
 
}
972
 
 
973
 
 
974
 
void TextureRender::dgradient() {
975
 
    // diagonal gradient code was written by Mike Cole <mike@mydot.com>
976
 
    // modified for interlacing by Brad Hughes
977
 
 
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;
985
 
 
986
 
    register unsigned int x, y;
987
 
 
988
 
    dry = drx = (float) (to->red() - from->red());
989
 
    dgy = dgx = (float) (to->green() - from->green());
990
 
    dby = dbx = (float) (to->blue() - from->blue());
991
 
 
992
 
    // Create X table
993
 
    drx /= w;
994
 
    dgx /= w;
995
 
    dbx /= w;
996
 
 
997
 
    for (x = 0; x < width; x++) {
998
 
        *(xt++) = (unsigned char) (xr);
999
 
        *(xt++) = (unsigned char) (xg);
1000
 
        *(xt++) = (unsigned char) (xb);
1001
 
 
1002
 
        xr += drx;
1003
 
        xg += dgx;
1004
 
        xb += dbx;
1005
 
    }
1006
 
 
1007
 
    // Create Y table
1008
 
    dry /= h;
1009
 
    dgy /= h;
1010
 
    dby /= h;
1011
 
 
1012
 
    for (y = 0; y < height; y++) {
1013
 
        *(yt++) = ((unsigned char) yr);
1014
 
        *(yt++) = ((unsigned char) yg);
1015
 
        *(yt++) = ((unsigned char) yb);
1016
 
 
1017
 
        yr += dry;
1018
 
        yg += dgy;
1019
 
        yb += dby;
1020
 
    }
1021
 
 
1022
 
    // Combine tables to create gradient
1023
 
 
1024
 
 
1025
 
    if (! interlaced) {
1026
 
 
1027
 
 
1028
 
        // normal dgradient
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);
1034
 
            }
1035
 
        }
1036
 
 
1037
 
    } else {
1038
 
        // faked interlacing effect
1039
 
        unsigned char channel, channel2;
1040
 
 
1041
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1042
 
            for (xt = xtable, x = 0; x < width; x++) {
1043
 
                if (y & 1) {
1044
 
                    channel = *(xt++) + *(yt);
1045
 
                    channel2 = (channel >> 1) + (channel >> 2);
1046
 
                    if (channel2 > channel) channel2 = 0;
1047
 
                    *(pr++) = channel2;
1048
 
 
1049
 
                    channel = *(xt++) + *(yt + 1);
1050
 
                    channel2 = (channel >> 1) + (channel >> 2);
1051
 
                    if (channel2 > channel) channel2 = 0;
1052
 
                    *(pg++) = channel2;
1053
 
 
1054
 
                    channel = *(xt++) + *(yt + 2);
1055
 
                    channel2 = (channel >> 1) + (channel >> 2);
1056
 
                    if (channel2 > channel) channel2 = 0;
1057
 
                    *(pb++) = channel2;
1058
 
                } else {
1059
 
                    channel = *(xt++) + *(yt);
1060
 
                    channel2 = channel + (channel >> 3);
1061
 
                    if (channel2 < channel) channel2 = ~0;
1062
 
                    *(pr++) = channel2;
1063
 
 
1064
 
                    channel = *(xt++) + *(yt + 1);
1065
 
                    channel2 = channel + (channel >> 3);
1066
 
                    if (channel2 < channel) channel2 = ~0;
1067
 
                    *(pg++) = channel2;
1068
 
 
1069
 
                    channel = *(xt++) + *(yt + 2);
1070
 
                    channel2 = channel + (channel >> 3);
1071
 
                    if (channel2 < channel) channel2 = ~0;
1072
 
                    *(pb++) = channel2;
1073
 
                }
1074
 
            }
1075
 
        }
1076
 
    }
1077
 
 
1078
 
 
1079
 
}
1080
 
 
1081
 
 
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;
1088
 
 
1089
 
    register unsigned int x, y;
1090
 
 
1091
 
    drx = (float) (to->red() - from->red());
1092
 
    dgx = (float) (to->green() - from->green());
1093
 
    dbx = (float) (to->blue() - from->blue());
1094
 
 
1095
 
    drx /= width;
1096
 
    dgx /= width;
1097
 
    dbx /= width;
1098
 
 
1099
 
    if (interlaced && height > 2) {
1100
 
        // faked interlacing effect
1101
 
        unsigned char channel, channel2;
1102
 
 
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;
1107
 
            *pr = channel2;
1108
 
 
1109
 
            channel = (unsigned char) xg;
1110
 
            channel2 = (channel >> 1) + (channel >> 2);
1111
 
            if (channel2 > channel) channel2 = 0;
1112
 
            *pg = channel2;
1113
 
 
1114
 
            channel = (unsigned char) xb;
1115
 
            channel2 = (channel >> 1) + (channel >> 2);
1116
 
            if (channel2 > channel) channel2 = 0;
1117
 
            *pb = channel2;
1118
 
 
1119
 
 
1120
 
            channel = (unsigned char) xr;
1121
 
            channel2 = channel + (channel >> 3);
1122
 
            if (channel2 < channel) channel2 = ~0;
1123
 
            *(pr + width) = channel2;
1124
 
 
1125
 
            channel = (unsigned char) xg;
1126
 
            channel2 = channel + (channel >> 3);
1127
 
            if (channel2 < channel) channel2 = ~0;
1128
 
            *(pg + width) = channel2;
1129
 
 
1130
 
            channel = (unsigned char) xb;
1131
 
            channel2 = channel + (channel >> 3);
1132
 
            if (channel2 < channel) channel2 = ~0;
1133
 
            *(pb + width) = channel2;
1134
 
 
1135
 
            xr += drx;
1136
 
            xg += dgx;
1137
 
            xb += dbx;
1138
 
        }
1139
 
 
1140
 
        pr += width;
1141
 
        pg += width;
1142
 
        pb += width;
1143
 
 
1144
 
        int offset;
1145
 
 
1146
 
        for (y = 2; y < height; y++, pr += width, pg += width, pb += width) {
1147
 
            if (y & 1) offset = width; else offset = 0;
1148
 
 
1149
 
            memcpy(pr, (red + offset), width);
1150
 
            memcpy(pg, (green + offset), width);
1151
 
            memcpy(pb, (blue + offset), width);
1152
 
        }
1153
 
    } else {
1154
 
 
1155
 
        // normal hgradient
1156
 
        for (x = 0; x < width; x++) {
1157
 
            *(pr++) = (unsigned char) (xr);
1158
 
            *(pg++) = (unsigned char) (xg);
1159
 
            *(pb++) = (unsigned char) (xb);
1160
 
 
1161
 
            xr += drx;
1162
 
            xg += dgx;
1163
 
            xb += dbx;
1164
 
        }
1165
 
 
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);
1170
 
        }
1171
 
 
1172
 
    }
1173
 
 
1174
 
}
1175
 
 
1176
 
 
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;
1183
 
 
1184
 
    register unsigned int y;
1185
 
 
1186
 
    dry = (float) (to->red() - from->red());
1187
 
    dgy = (float) (to->green() - from->green());
1188
 
    dby = (float) (to->blue() - from->blue());
1189
 
 
1190
 
    dry /= height;
1191
 
    dgy /= height;
1192
 
    dby /= height;
1193
 
 
1194
 
    if (interlaced) {
1195
 
        // faked interlacing effect
1196
 
        unsigned char channel, channel2;
1197
 
 
1198
 
        for (y = 0; y < height; y++, pr += width, pg += width, pb += width) {
1199
 
            if (y & 1) {
1200
 
                channel = (unsigned char) yr;
1201
 
                channel2 = (channel >> 1) + (channel >> 2);
1202
 
                if (channel2 > channel) channel2 = 0;
1203
 
                memset(pr, channel2, width);
1204
 
 
1205
 
                channel = (unsigned char) yg;
1206
 
                channel2 = (channel >> 1) + (channel >> 2);
1207
 
                if (channel2 > channel) channel2 = 0;
1208
 
                memset(pg, channel2, width);
1209
 
 
1210
 
                channel = (unsigned char) yb;
1211
 
                channel2 = (channel >> 1) + (channel >> 2);
1212
 
                if (channel2 > channel) channel2 = 0;
1213
 
                memset(pb, channel2, width);
1214
 
            } else {
1215
 
                channel = (unsigned char) yr;
1216
 
                channel2 = channel + (channel >> 3);
1217
 
                if (channel2 < channel) channel2 = ~0;
1218
 
                memset(pr, channel2, width);
1219
 
 
1220
 
                channel = (unsigned char) yg;
1221
 
                channel2 = channel + (channel >> 3);
1222
 
                if (channel2 < channel) channel2 = ~0;
1223
 
                memset(pg, channel2, width);
1224
 
 
1225
 
                channel = (unsigned char) yb;
1226
 
                channel2 = channel + (channel >> 3);
1227
 
                if (channel2 < channel) channel2 = ~0;
1228
 
                memset(pb, channel2, width);
1229
 
            }
1230
 
 
1231
 
            yr += dry;
1232
 
            yg += dgy;
1233
 
            yb += dby;
1234
 
        }
1235
 
    } else {
1236
 
 
1237
 
        // normal vgradient
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);
1242
 
 
1243
 
            yr += dry;
1244
 
            yg += dgy;
1245
 
            yb += dby;
1246
 
        }
1247
 
    }
1248
 
 
1249
 
 
1250
 
}
1251
 
 
1252
 
 
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
1257
 
 
1258
 
    float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby,
1259
 
        xr, xg, xb;
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;
1264
 
 
1265
 
    register unsigned int x, y;
1266
 
 
1267
 
    dry = drx = (float) (to->red() - from->red());
1268
 
    dgy = dgx = (float) (to->green() - from->green());
1269
 
    dby = dbx = (float) (to->blue() - from->blue());
1270
 
 
1271
 
    rsign = (drx < 0) ? -1 : 1;
1272
 
    gsign = (dgx < 0) ? -1 : 1;
1273
 
    bsign = (dbx < 0) ? -1 : 1;
1274
 
 
1275
 
    xr = yr = (drx / 2);
1276
 
    xg = yg = (dgx / 2);
1277
 
    xb = yb = (dbx / 2);
1278
 
 
1279
 
    // Create X table
1280
 
    drx /= width;
1281
 
    dgx /= width;
1282
 
    dbx /= width;
1283
 
 
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);
1288
 
 
1289
 
        xr -= drx;
1290
 
        xg -= dgx;
1291
 
        xb -= dbx;
1292
 
    }
1293
 
 
1294
 
    // Create Y table
1295
 
    dry /= height;
1296
 
    dgy /= height;
1297
 
    dby /= height;
1298
 
 
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));
1303
 
 
1304
 
        yr -= dry;
1305
 
        yg -= dgy;
1306
 
        yb -= dby;
1307
 
    }
1308
 
 
1309
 
    // Combine tables to create gradient
1310
 
 
1311
 
 
1312
 
    if (! interlaced) {
1313
 
 
1314
 
        // normal pgradient
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))));
1320
 
            }
1321
 
        }
1322
 
 
1323
 
    } else {
1324
 
        // faked interlacing effect
1325
 
        unsigned char channel, channel2;
1326
 
 
1327
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1328
 
            for (xt = xtable, x = 0; x < width; x++) {
1329
 
                if (y & 1) {
1330
 
                    channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1331
 
                    channel2 = (channel >> 1) + (channel >> 2);
1332
 
                    if (channel2 > channel) channel2 = 0;
1333
 
                    *(pr++) = channel2;
1334
 
 
1335
 
                    channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1336
 
                    channel2 = (channel >> 1) + (channel >> 2);
1337
 
                    if (channel2 > channel) channel2 = 0;
1338
 
                    *(pg++) = channel2;
1339
 
 
1340
 
                    channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1341
 
                    channel2 = (channel >> 1) + (channel >> 2);
1342
 
                    if (channel2 > channel) channel2 = 0;
1343
 
                    *(pb++) = channel2;
1344
 
                } else {
1345
 
                    channel = (unsigned char) (tr - (rsign * (*(xt++) + *(yt))));
1346
 
                    channel2 = channel + (channel >> 3);
1347
 
                    if (channel2 < channel) channel2 = ~0;
1348
 
                    *(pr++) = channel2;
1349
 
 
1350
 
                    channel = (unsigned char) (tg - (gsign * (*(xt++) + *(yt + 1))));
1351
 
                    channel2 = channel + (channel >> 3);
1352
 
                    if (channel2 < channel) channel2 = ~0;
1353
 
                    *(pg++) = channel2;
1354
 
 
1355
 
                    channel = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2))));
1356
 
                    channel2 = channel + (channel >> 3);
1357
 
                    if (channel2 < channel) channel2 = ~0;
1358
 
                    *(pb++) = channel2;
1359
 
                }
1360
 
            }
1361
 
        }
1362
 
    }
1363
 
 
1364
 
}
1365
 
 
1366
 
 
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
1371
 
 
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;
1377
 
 
1378
 
    register unsigned int x, y;
1379
 
 
1380
 
    dry = drx = (float) (to->red() - from->red());
1381
 
    dgy = dgx = (float) (to->green() - from->green());
1382
 
    dby = dbx = (float) (to->blue() - from->blue());
1383
 
 
1384
 
    rsign = (drx < 0) ? -2 : 2;
1385
 
    gsign = (dgx < 0) ? -2 : 2;
1386
 
    bsign = (dbx < 0) ? -2 : 2;
1387
 
 
1388
 
    xr = yr = (drx / 2);
1389
 
    xg = yg = (dgx / 2);
1390
 
    xb = yb = (dbx / 2);
1391
 
 
1392
 
    // Create X table
1393
 
    drx /= width;
1394
 
    dgx /= width;
1395
 
    dbx /= width;
1396
 
 
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);
1401
 
 
1402
 
        xr -= drx;
1403
 
        xg -= dgx;
1404
 
        xb -= dbx;
1405
 
    }
1406
 
 
1407
 
    // Create Y table
1408
 
    dry /= height;
1409
 
    dgy /= height;
1410
 
    dby /= height;
1411
 
 
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));
1416
 
 
1417
 
        yr -= dry;
1418
 
        yg -= dgy;
1419
 
        yb -= dby;
1420
 
    }
1421
 
 
1422
 
    // Combine tables to create gradient
1423
 
 
1424
 
 
1425
 
    if (! interlaced) {
1426
 
 
1427
 
        // normal rgradient
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))));
1433
 
            }
1434
 
        }
1435
 
 
1436
 
    } else {
1437
 
        // faked interlacing effect
1438
 
        unsigned char channel, channel2;
1439
 
 
1440
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1441
 
            for (xt = xtable, x = 0; x < width; x++) {
1442
 
                if (y & 1) {
1443
 
                    channel = (unsigned char) (tr - (rsign * std::max(*(xt++), *(yt))));
1444
 
                    channel2 = (channel >> 1) + (channel >> 2);
1445
 
                    if (channel2 > channel) channel2 = 0;
1446
 
                    *(pr++) = channel2;
1447
 
 
1448
 
                    channel = (unsigned char) (tg - (gsign * std::max(*(xt++), *(yt + 1))));
1449
 
                    channel2 = (channel >> 1) + (channel >> 2);
1450
 
                    if (channel2 > channel) channel2 = 0;
1451
 
                    *(pg++) = channel2;
1452
 
 
1453
 
                    channel = (unsigned char) (tb - (bsign * std::max(*(xt++), *(yt + 2))));
1454
 
                    channel2 = (channel >> 1) + (channel >> 2);
1455
 
                    if (channel2 > channel) channel2 = 0;
1456
 
                    *(pb++) = channel2;
1457
 
                } else {
1458
 
                    channel = (unsigned char) (tr - (rsign * std::max(*(xt++), *(yt))));
1459
 
                    channel2 = channel + (channel >> 3);
1460
 
                    if (channel2 < channel) channel2 = ~0;
1461
 
                    *(pr++) = channel2;
1462
 
 
1463
 
                    channel = (unsigned char) (tg - (gsign * std::max(*(xt++), *(yt + 1))));
1464
 
                    channel2 = channel + (channel >> 3);
1465
 
                    if (channel2 < channel) channel2 = ~0;
1466
 
                    *(pg++) = channel2;
1467
 
 
1468
 
                    channel = (unsigned char) (tb - (bsign * std::max(*(xt++), *(yt + 2))));
1469
 
                    channel2 = channel + (channel >> 3);
1470
 
                    if (channel2 < channel) channel2 = ~0;
1471
 
                    *(pb++) = channel2;
1472
 
                }
1473
 
            }
1474
 
        }
1475
 
    }
1476
 
 
1477
 
}
1478
 
 
1479
 
 
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
1484
 
 
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();
1492
 
 
1493
 
    register unsigned int x, y;
1494
 
 
1495
 
    dry = drx = (float) (to->red() - from->red());
1496
 
    dgy = dgx = (float) (to->green() - from->green());
1497
 
    dby = dbx = (float) (to->blue() - from->blue());
1498
 
 
1499
 
    rsign = (drx < 0) ? -1 : 1;
1500
 
    gsign = (dgx < 0) ? -1 : 1;
1501
 
    bsign = (dbx < 0) ? -1 : 1;
1502
 
 
1503
 
    xr = yr = (drx / 2);
1504
 
    xg = yg = (dgx / 2);
1505
 
    xb = yb = (dbx / 2);
1506
 
 
1507
 
    // Create X table
1508
 
    drx /= width;
1509
 
    dgx /= width;
1510
 
    dbx /= width;
1511
 
 
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);
1516
 
 
1517
 
        xr -= drx;
1518
 
        xg -= dgx;
1519
 
        xb -= dbx;
1520
 
    }
1521
 
 
1522
 
    // Create Y table
1523
 
    dry /= height;
1524
 
    dgy /= height;
1525
 
    dby /= height;
1526
 
 
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);
1531
 
 
1532
 
        yr -= dry;
1533
 
        yg -= dgy;
1534
 
        yb -= dby;
1535
 
    }
1536
 
 
1537
 
    // Combine tables to create gradient
1538
 
    if (! interlaced) {
1539
 
        // normal egradient
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))));
1548
 
            }
1549
 
        }
1550
 
 
1551
 
    } else {
1552
 
        // faked interlacing effect
1553
 
        unsigned char channel, channel2;
1554
 
 
1555
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1556
 
            for (xt = xtable, x = 0; x < width; x++) {
1557
 
                if (y & 1) {
1558
 
                    channel = (unsigned char)
1559
 
                        (tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
1560
 
                    channel2 = (channel >> 1) + (channel >> 2);
1561
 
                    if (channel2 > channel) channel2 = 0;
1562
 
                    *(pr++) = channel2;
1563
 
 
1564
 
                    channel = (unsigned char)
1565
 
                        (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
1566
 
                    channel2 = (channel >> 1) + (channel >> 2);
1567
 
                    if (channel2 > channel) channel2 = 0;
1568
 
                    *(pg++) = channel2;
1569
 
 
1570
 
                    channel = (unsigned char)
1571
 
                        (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
1572
 
                    channel2 = (channel >> 1) + (channel >> 2);
1573
 
                    if (channel2 > channel) channel2 = 0;
1574
 
                    *(pb++) = channel2;
1575
 
                } else {
1576
 
                    channel = (unsigned char)
1577
 
                        (tr - (rsign * control.getSqrt(*(xt++) + *(yt))));
1578
 
                    channel2 = channel + (channel >> 3);
1579
 
                    if (channel2 < channel) channel2 = ~0;
1580
 
                    *(pr++) = channel2;
1581
 
 
1582
 
                    channel = (unsigned char)
1583
 
                        (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1))));
1584
 
                    channel2 = channel + (channel >> 3);
1585
 
                    if (channel2 < channel) channel2 = ~0;
1586
 
                    *(pg++) = channel2;
1587
 
 
1588
 
                    channel = (unsigned char)
1589
 
                        (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2))));
1590
 
                    channel2 = channel + (channel >> 3);
1591
 
                    if (channel2 < channel) channel2 = ~0;
1592
 
                    *(pb++) = channel2;
1593
 
                }
1594
 
            }
1595
 
        }
1596
 
    }
1597
 
 
1598
 
}
1599
 
 
1600
 
 
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
1605
 
 
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(),
1611
 
        tg = to->green(),
1612
 
        tb = to->blue();
1613
 
 
1614
 
    register unsigned int x, y;
1615
 
 
1616
 
    dry = drx = (float) (to->red() - from->red());
1617
 
    dgy = dgx = (float) (to->green() - from->green());
1618
 
    dby = dbx = (float) (to->blue() - from->blue());
1619
 
 
1620
 
    rsign = (drx < 0) ? -2 : 2;
1621
 
    gsign = (dgx < 0) ? -2 : 2;
1622
 
    bsign = (dbx < 0) ? -2 : 2;
1623
 
 
1624
 
    xr = yr = (drx / 2);
1625
 
    xg = yg = (dgx / 2);
1626
 
    xb = yb = (dbx / 2);
1627
 
 
1628
 
    // Create X table
1629
 
    drx /= width;
1630
 
    dgx /= width;
1631
 
    dbx /= width;
1632
 
 
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);
1637
 
 
1638
 
        xr -= drx;
1639
 
        xg -= dgx;
1640
 
        xb -= dbx;
1641
 
    }
1642
 
 
1643
 
    // Create Y table
1644
 
    dry /= height;
1645
 
    dgy /= height;
1646
 
    dby /= height;
1647
 
 
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));
1652
 
 
1653
 
        yr -= dry;
1654
 
        yg -= dgy;
1655
 
        yb -= dby;
1656
 
    }
1657
 
 
1658
 
    // Combine tables to create gradient
1659
 
    if (! interlaced) {
1660
 
 
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))));
1667
 
            }
1668
 
        }
1669
 
 
1670
 
    } else {
1671
 
        // faked interlacing effect
1672
 
        unsigned char channel, channel2;
1673
 
 
1674
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1675
 
            for (xt = xtable, x = 0; x < width; x++) {
1676
 
                if (y & 1) {
1677
 
                    channel = (unsigned char) (tr - (rsign * std::min(*(xt++), *(yt))));
1678
 
                    channel2 = (channel >> 1) + (channel >> 2);
1679
 
                    if (channel2 > channel) channel2 = 0;
1680
 
                    *(pr++) = channel2;
1681
 
 
1682
 
                    channel = (unsigned char) (tg - (bsign * std::min(*(xt++), *(yt + 1))));
1683
 
                    channel2 = (channel >> 1) + (channel >> 2);
1684
 
                    if (channel2 > channel) channel2 = 0;
1685
 
                    *(pg++) = channel2;
1686
 
 
1687
 
                    channel = (unsigned char) (tb - (gsign * std::min(*(xt++), *(yt + 2))));
1688
 
                    channel2 = (channel >> 1) + (channel >> 2);
1689
 
                    if (channel2 > channel) channel2 = 0;
1690
 
                    *(pb++) = channel2;
1691
 
                } else {
1692
 
                    channel = (unsigned char) (tr - (rsign * std::min(*(xt++), *(yt))));
1693
 
                    channel2 = channel + (channel >> 3);
1694
 
                    if (channel2 < channel) channel2 = ~0;
1695
 
                    *(pr++) = channel2;
1696
 
 
1697
 
                    channel = (unsigned char) (tg - (gsign * std::min(*(xt++), *(yt + 1))));
1698
 
                    channel2 = channel + (channel >> 3);
1699
 
                    if (channel2 < channel) channel2 = ~0;
1700
 
                    *(pg++) = channel2;
1701
 
 
1702
 
                    channel = (unsigned char) (tb - (bsign * std::min(*(xt++), *(yt + 2))));
1703
 
                    channel2 = channel + (channel >> 3);
1704
 
                    if (channel2 < channel) channel2 = ~0;
1705
 
                    *(pb++) = channel2;
1706
 
                }
1707
 
            }
1708
 
        }
1709
 
    }
1710
 
 
1711
 
}
1712
 
 
1713
 
 
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
1718
 
 
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;
1725
 
 
1726
 
    register unsigned int x, y;
1727
 
 
1728
 
    dry = drx = (float) (to->red() - from->red());
1729
 
    dgy = dgx = (float) (to->green() - from->green());
1730
 
    dby = dbx = (float) (to->blue() - from->blue());
1731
 
 
1732
 
    // Create X table
1733
 
    drx /= w;
1734
 
    dgx /= w;
1735
 
    dbx /= w;
1736
 
 
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;
1741
 
 
1742
 
        xr += drx;
1743
 
        xg += dgx;
1744
 
        xb += dbx;
1745
 
    }
1746
 
 
1747
 
    // Create Y table
1748
 
    dry /= h;
1749
 
    dgy /= h;
1750
 
    dby /= h;
1751
 
 
1752
 
    for (yt = ytable, y = 0; y < height; y++) {
1753
 
        *(yt++) = (unsigned char) yr;
1754
 
        *(yt++) = (unsigned char) yg;
1755
 
        *(yt++) = (unsigned char) yb;
1756
 
 
1757
 
        yr += dry;
1758
 
        yg += dgy;
1759
 
        yb += dby;
1760
 
    }
1761
 
 
1762
 
    // Combine tables to create gradient
1763
 
 
1764
 
    if (! interlaced) {
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);
1771
 
            }
1772
 
        }
1773
 
 
1774
 
    } else {
1775
 
        // faked interlacing effect
1776
 
        unsigned char channel, channel2;
1777
 
 
1778
 
        for (yt = ytable, y = 0; y < height; y++, yt += 3) {
1779
 
            for (xt = xtable, x = 0; x < width; x++) {
1780
 
                if (y & 1) {
1781
 
                    channel = *(xt++) + *(yt);
1782
 
                    channel2 = (channel >> 1) + (channel >> 2);
1783
 
                    if (channel2 > channel) channel2 = 0;
1784
 
                    *(pr++) = channel2;
1785
 
 
1786
 
                    channel = *(xt++) + *(yt + 1);
1787
 
                    channel2 = (channel >> 1) + (channel >> 2);
1788
 
                    if (channel2 > channel) channel2 = 0;
1789
 
                    *(pg++) = channel2;
1790
 
 
1791
 
                    channel = *(xt++) + *(yt + 2);
1792
 
                    channel2 = (channel >> 1) + (channel >> 2);
1793
 
                    if (channel2 > channel) channel2 = 0;
1794
 
                    *(pb++) = channel2;
1795
 
                } else {
1796
 
                    channel = *(xt++) + *(yt);
1797
 
                    channel2 = channel + (channel >> 3);
1798
 
                    if (channel2 < channel) channel2 = ~0;
1799
 
                    *(pr++) = channel2;
1800
 
 
1801
 
                    channel = *(xt++) + *(yt + 1);
1802
 
                    channel2 = channel + (channel >> 3);
1803
 
                    if (channel2 < channel) channel2 = ~0;
1804
 
                    *(pg++) = channel2;
1805
 
 
1806
 
                    channel = *(xt++) + *(yt + 2);
1807
 
                    channel2 = channel + (channel >> 3);
1808
 
                    if (channel2 < channel) channel2 = ~0;
1809
 
                    *(pb++) = channel2;
1810
 
                }
1811
 
            }
1812
 
        }
1813
 
    }
1814
 
 
1815
 
}
1816
 
 
1817
 
}; // end namespace FbTk