OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [mw/] [src/] [engine/] [devdraw.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
 * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
3
 * Portions Copyright (c) 1991 David I. Bell
4
 * Permission is granted to use, distribute, or modify this source,
5
 * provided that this copyright notice remains intact.
6
 *
7
 * Device-independent mid level drawing and color routines.
8
 *
9
 * These routines do the necessary range checking, clipping, and cursor
10
 * overwriting checks, and then call the lower level device dependent
11
 * routines to actually do the drawing.  The lower level routines are
12
 * only called when it is known that all the pixels to be drawn are
13
 * within the device area and are visible.
14
 */
15
/*#define NDEBUG*/
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <assert.h>
19
#include "device.h"
20
 
21
extern MWPIXELVAL gr_foreground;      /* current foreground color */
22
extern MWPIXELVAL gr_background;      /* current background color */
23
extern MWBOOL     gr_usebg;           /* TRUE if background drawn in pixmaps */
24
extern int        gr_mode;            /* drawing mode */
25
extern MWPALENTRY gr_palette[256];    /* current palette*/
26
extern int        gr_firstuserpalentry;/* first user-changable palette entry*/
27
extern int        gr_nextpalentry;    /* next available palette entry*/
28
 
29
/*static*/ void drawpoint(PSD psd,MWCOORD x, MWCOORD y);
30
/*static*/ void drawrow(PSD psd,MWCOORD x1,MWCOORD x2,MWCOORD y);
31
static void drawcol(PSD psd,MWCOORD x,MWCOORD y1,MWCOORD y2);
32
 
33
/*
34
 * Set the drawing mode for future calls.
35
 */
36
int
37
GdSetMode(int mode)
38
{
39
        int     oldmode = gr_mode;
40
 
41
        gr_mode = mode;
42
        return oldmode;
43
}
44
 
45
/*
46
 * Set whether or not the background is used for drawing pixmaps and text.
47
 */
48
MWBOOL
49
GdSetUseBackground(MWBOOL flag)
50
{
51
        MWBOOL  oldusebg = gr_usebg;
52
 
53
        gr_usebg = flag;
54
        return oldusebg;
55
}
56
 
57
/*
58
 * Set the foreground color for drawing.
59
 */
60
MWPIXELVAL
61
GdSetForeground(MWPIXELVAL fg)
62
{
63
        MWPIXELVAL      oldfg = gr_foreground;
64
 
65
        gr_foreground = fg;
66
        return oldfg;
67
}
68
 
69
/*
70
 * Set the background color for bitmap and text backgrounds.
71
 */
72
MWPIXELVAL
73
GdSetBackground(MWPIXELVAL bg)
74
{
75
        MWPIXELVAL      oldbg = gr_background;
76
 
77
        gr_background = bg;
78
        return oldbg;
79
}
80
 
81
/*
82
 * Draw a point using the current clipping region and foreground color.
83
 */
84
void
85
GdPoint(PSD psd, MWCOORD x, MWCOORD y)
86
{
87
        if (GdClipPoint(psd, x, y)) {
88
                psd->DrawPixel(psd, x, y, gr_foreground);
89
                GdFixCursor(psd);
90
        }
91
}
92
 
93
/*
94
 * Draw an arbitrary line using the current clipping region and foreground color
95
 * If bDrawLastPoint is FALSE, draw up to but not including point x2, y2.
96
 *
97
 * This routine is the only routine that adjusts coordinates for supporting
98
 * two different types of upper levels, those that draw the last point
99
 * in a line, and those that draw up to the last point.  All other local
100
 * routines draw the last point.  This gives this routine a bit more overhead,
101
 * but keeps overall complexity down.
102
 */
103
void
104
GdLine(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD x2, MWCOORD y2,
105
        MWBOOL bDrawLastPoint)
106
{
107
  int xdelta;                   /* width of rectangle around line */
108
  int ydelta;                   /* height of rectangle around line */
109
  int xinc;                     /* increment for moving x coordinate */
110
  int yinc;                     /* increment for moving y coordinate */
111
  int rem;                      /* current remainder */
112
  MWCOORD temp;
113
 
114
  /* See if the line is horizontal or vertical. If so, then call
115
   * special routines.
116
   */
117
  if (y1 == y2) {
118
        /*
119
         * Adjust coordinates if not drawing last point.  Tricky.
120
         */
121
        if(!bDrawLastPoint) {
122
                if (x1 > x2) {
123
                        temp = x1;
124
                        x1 = x2 + 1;
125
                        x2 = temp;
126
                } else
127
                        --x2;
128
        }
129
 
130
        /* call faster line drawing routine*/
131
        drawrow(psd, x1, x2, y1);
132
        GdFixCursor(psd);
133
        return;
134
  }
135
  if (x1 == x2) {
136
        /*
137
         * Adjust coordinates if not drawing last point.  Tricky.
138
         */
139
        if(!bDrawLastPoint) {
140
                if (y1 > y2) {
141
                        temp = y1;
142
                        y1 = y2 + 1;
143
                        y2 = temp;
144
                } else
145
                        --y2;
146
        }
147
 
148
        /* call faster line drawing routine*/
149
        drawcol(psd, x1, y1, y2);
150
        GdFixCursor(psd);
151
        return;
152
  }
153
 
154
  /* See if the line is either totally visible or totally invisible. If
155
   * so, then the line drawing is easy.
156
   */
157
  switch (GdClipArea(psd, x1, y1, x2, y2)) {
158
      case CLIP_VISIBLE:
159
        /*
160
         * For size considerations, there's no low-level bresenham
161
         * line draw, so we've got to draw all non-vertical
162
         * and non-horizontal lines with per-point
163
         * clipping for the time being
164
        psd->Line(psd, x1, y1, x2, y2, gr_foreground);
165
        GdFixCursor(psd);
166
        return;
167
         */
168
        break;
169
      case CLIP_INVISIBLE:
170
        return;
171
  }
172
 
173
  /* The line may be partially obscured. Do the draw line algorithm
174
   * checking each point against the clipping regions.
175
   */
176
  xdelta = x2 - x1;
177
  ydelta = y2 - y1;
178
  if (xdelta < 0) xdelta = -xdelta;
179
  if (ydelta < 0) ydelta = -ydelta;
180
  xinc = (x2 > x1) ? 1 : -1;
181
  yinc = (y2 > y1) ? 1 : -1;
182
  if (GdClipPoint(psd, x1, y1))
183
          psd->DrawPixel(psd, x1, y1, gr_foreground);
184
  if (xdelta >= ydelta) {
185
        rem = xdelta / 2;
186
        for(;;) {
187
                if(!bDrawLastPoint && x1 == x2)
188
                        break;
189
                x1 += xinc;
190
                rem += ydelta;
191
                if (rem >= xdelta) {
192
                        rem -= xdelta;
193
                        y1 += yinc;
194
                }
195
                if (GdClipPoint(psd, x1, y1))
196
                        psd->DrawPixel(psd, x1, y1, gr_foreground);
197
                if(bDrawLastPoint && x1 == x2)
198
                        break;
199
        }
200
  } else {
201
        rem = ydelta / 2;
202
        for(;;) {
203
                if(!bDrawLastPoint && y1 == y2)
204
                        break;
205
                y1 += yinc;
206
                rem += xdelta;
207
                if (rem >= ydelta) {
208
                        rem -= ydelta;
209
                        x1 += xinc;
210
                }
211
                if (GdClipPoint(psd, x1, y1))
212
                        psd->DrawPixel(psd, x1, y1, gr_foreground);
213
                if(bDrawLastPoint && y1 == y2)
214
                        break;
215
        }
216
  }
217
  GdFixCursor(psd);
218
}
219
 
220
/* Draw a point in the foreground color, applying clipping if necessary*/
221
/*static*/ void
222
drawpoint(PSD psd, MWCOORD x, MWCOORD y)
223
{
224
        if (GdClipPoint(psd, x, y))
225
                psd->DrawPixel(psd, x, y, gr_foreground);
226
}
227
 
228
/* Draw a horizontal line from x1 to and including x2 in the
229
 * foreground color, applying clipping if necessary.
230
 */
231
/*static*/ void
232
drawrow(PSD psd, MWCOORD x1, MWCOORD x2, MWCOORD y)
233
{
234
  MWCOORD temp;
235
 
236
  /* reverse endpoints if necessary*/
237
  if (x1 > x2) {
238
        temp = x1;
239
        x1 = x2;
240
        x2 = temp;
241
  }
242
 
243
  /* clip to physical device*/
244
  if (x1 < 0)
245
          x1 = 0;
246
  if (x2 >= psd->xvirtres)
247
          x2 = psd->xvirtres - 1;
248
 
249
  /* check cursor intersect once for whole line*/
250
  GdCheckCursor(psd, x1, y, x2, y);
251
 
252
  while (x1 <= x2) {
253
        if (GdClipPoint(psd, x1, y)) {
254
                temp = MWMIN(clipmaxx, x2);
255
                psd->DrawHorzLine(psd, x1, temp, y, gr_foreground);
256
        } else
257
                temp = MWMIN(clipmaxx, x2);
258
        x1 = temp + 1;
259
  }
260
}
261
 
262
/* Draw a vertical line from y1 to and including y2 in the
263
 * foreground color, applying clipping if necessary.
264
 */
265
static void
266
drawcol(PSD psd, MWCOORD x,MWCOORD y1,MWCOORD y2)
267
{
268
  MWCOORD temp;
269
 
270
  /* reverse endpoints if necessary*/
271
  if (y1 > y2) {
272
        temp = y1;
273
        y1 = y2;
274
        y2 = temp;
275
  }
276
 
277
  /* clip to physical device*/
278
  if (y1 < 0)
279
          y1 = 0;
280
  if (y2 >= psd->yvirtres)
281
          y2 = psd->yvirtres - 1;
282
 
283
  /* check cursor intersect once for whole line*/
284
  GdCheckCursor(psd, x, y1, x, y2);
285
 
286
  while (y1 <= y2) {
287
        if (GdClipPoint(psd, x, y1)) {
288
                temp = MWMIN(clipmaxy, y2);
289
                psd->DrawVertLine(psd, x, y1, temp, gr_foreground);
290
        } else
291
                temp = MWMIN(clipmaxy, y2);
292
        y1 = temp + 1;
293
  }
294
}
295
 
296
/* Draw a rectangle in the foreground color, applying clipping if necessary.
297
 * This is careful to not draw points multiple times in case the rectangle
298
 * is being drawn using XOR.
299
 */
300
void
301
GdRect(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height)
302
{
303
  MWCOORD maxx;
304
  MWCOORD maxy;
305
 
306
  if (width <= 0 || height <= 0)
307
          return;
308
  maxx = x + width - 1;
309
  maxy = y + height - 1;
310
  drawrow(psd, x, maxx, y);
311
  if (height > 1)
312
          drawrow(psd, x, maxx, maxy);
313
  if (height < 3)
314
          return;
315
  y++;
316
  maxy--;
317
  drawcol(psd, x, y, maxy);
318
  if (width > 1)
319
          drawcol(psd, maxx, y, maxy);
320
  GdFixCursor(psd);
321
}
322
 
323
/* Draw a filled in rectangle in the foreground color, applying
324
 * clipping if necessary.
325
 */
326
void
327
GdFillRect(PSD psd, MWCOORD x1, MWCOORD y1, MWCOORD width, MWCOORD height)
328
{
329
  MWCOORD x2 = x1+width-1;
330
  MWCOORD y2 = y1+height-1;
331
 
332
  if (width <= 0 || height <= 0)
333
          return;
334
 
335
  /* See if the rectangle is either totally visible or totally
336
   * invisible. If so, then the rectangle drawing is easy.
337
   */
338
  switch (GdClipArea(psd, x1, y1, x2, y2)) {
339
      case CLIP_VISIBLE:
340
        psd->FillRect(psd, x1, y1, x2, y2, gr_foreground);
341
        GdFixCursor(psd);
342
        return;
343
 
344
      case CLIP_INVISIBLE:
345
        return;
346
  }
347
 
348
  /* The rectangle may be partially obstructed. So do it line by line. */
349
  while (y1 <= y2)
350
          drawrow(psd, x1, x2, y1++);
351
  GdFixCursor(psd);
352
}
353
 
354
/*
355
 * Draw a rectangular area using the current clipping region and the
356
 * specified bit map.  This differs from rectangle drawing in that the
357
 * rectangle is drawn using the foreground color and possibly the background
358
 * color as determined by the bit map.  Each row of bits is aligned to the
359
 * next bitmap word boundary (so there is padding at the end of the row).
360
 * The background bit values are only written if the gr_usebg flag
361
 * is set.
362
 */
363
void
364
GdBitmap(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
365
        MWIMAGEBITS *imagebits)
366
{
367
  MWCOORD minx;
368
  MWCOORD maxx;
369
  MWPIXELVAL savecolor;         /* saved foreground color */
370
  MWIMAGEBITS bitvalue = 0;      /* bitmap word value */
371
  int bitcount;                 /* number of bits left in bitmap word */
372
 
373
  switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
374
      case CLIP_VISIBLE:
375
        /*
376
         * For size considerations, there's no low-level bitmap
377
         * draw so we've got to draw everything with per-point
378
         * clipping for the time being.
379
        if (gr_usebg)
380
                psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
381
                        gr_background);
382
        psd->DrawBitmap(psd, x, y, width, height, imagebits, gr_foreground);
383
        return;
384
        */
385
        break;
386
 
387
      case CLIP_INVISIBLE:
388
        return;
389
  }
390
 
391
  /* The rectangle is partially visible, so must do clipping. First
392
   * fill a rectangle in the background color if necessary.
393
   */
394
  if (gr_usebg) {
395
        savecolor = gr_foreground;
396
        gr_foreground = gr_background;
397
        /* note: change to fillrect*/
398
        GdFillRect(psd, x, y, width, height);
399
        gr_foreground = savecolor;
400
  }
401
  minx = x;
402
  maxx = x + width - 1;
403
  bitcount = 0;
404
  while (height > 0) {
405
        if (bitcount <= 0) {
406
                bitcount = MWIMAGE_BITSPERIMAGE;
407
                bitvalue = *imagebits++;
408
        }
409
        if (MWIMAGE_TESTBIT(bitvalue) && GdClipPoint(psd, x, y))
410
                psd->DrawPixel(psd, x, y, gr_foreground);
411
        bitvalue = MWIMAGE_SHIFTBIT(bitvalue);
412
        bitcount--;
413
        if (x++ == maxx) {
414
                x = minx;
415
                y++;
416
                height--;
417
                bitcount = 0;
418
        }
419
  }
420
  GdFixCursor(psd);
421
}
422
 
423
/*
424
 * Return true if color is in palette
425
 */
426
MWBOOL
427
GdColorInPalette(MWCOLORVAL cr,MWPALENTRY *palette,int palsize)
428
{
429
        int     i;
430
 
431
        for(i=0; i<palsize; ++i)
432
                if(GETPALENTRY(palette, i) == cr)
433
                        return TRUE;
434
        return FALSE;
435
}
436
 
437
/*
438
 * Create a MWPIXELVAL conversion table between the passed palette
439
 * and the in-use palette.  The system palette is loaded/merged according
440
 * to fLoadType.
441
 */
442
void
443
GdMakePaletteConversionTable(PSD psd,MWPALENTRY *palette,int palsize,
444
        MWPIXELVAL *convtable,int fLoadType)
445
{
446
        int             i;
447
        MWCOLORVAL      cr;
448
        int             newsize, nextentry;
449
        MWPALENTRY      newpal[256];
450
 
451
        /*
452
         * Check for load palette completely, or add colors
453
         * from passed palette to system palette until full.
454
         */
455
        if(psd->pixtype == MWPF_PALETTE) {
456
            switch(fLoadType) {
457
            case LOADPALETTE:
458
                /* Load palette from beginning with image's palette.
459
                 * First palette entries are Microwindows colors
460
                 * and not changed.
461
                 */
462
                GdSetPalette(psd, gr_firstuserpalentry, palsize, palette);
463
                break;
464
 
465
            case MERGEPALETTE:
466
                /* get system palette*/
467
                for(i=0; i<(int)psd->ncolors; ++i)
468
                        newpal[i] = gr_palette[i];
469
 
470
                /* merge passed palette into system palette*/
471
                newsize = 0;
472
                nextentry = gr_nextpalentry;
473
 
474
                /* if color missing and there's room, add it*/
475
                for(i=0; i<palsize && nextentry < (int)psd->ncolors; ++i) {
476
                        cr = GETPALENTRY(palette, i);
477
                        if(!GdColorInPalette(cr, newpal, nextentry)) {
478
                                newpal[nextentry++] = palette[i];
479
                                ++newsize;
480
                        }
481
                }
482
 
483
                /* set the new palette if any color was added*/
484
                if(newsize) {
485
                        GdSetPalette(psd, gr_nextpalentry, newsize,
486
                                &newpal[gr_nextpalentry]);
487
                        gr_nextpalentry += newsize;
488
                }
489
                break;
490
            }
491
        }
492
 
493
        /*
494
         * Build conversion table from inuse system palette and
495
         * passed palette.  This will load RGB values directly
496
         * if running truecolor, otherwise it will find the
497
         * nearest color from the inuse palette.
498
         * FIXME: tag the conversion table to the bitmap image
499
         */
500
        for(i=0; i<palsize; ++i) {
501
                cr = GETPALENTRY(palette, i);
502
                convtable[i] = GdFindColor(cr);
503
        }
504
}
505
 
506
/*
507
 * Draw a color bitmap image in 1, 4, 8, 24 or 32 bits per pixel.  The
508
 * Microwindows color image format is DWORD padded bytes, with
509
 * the upper bits corresponding to the left side (identical to
510
 * the MS Windows format).  This format is currently different
511
 * than the MWIMAGEBITS format, which uses word-padded bits
512
 * for monochrome display only, where the upper bits in the word
513
 * correspond with the left side.
514
 */
515
void
516
GdDrawImage(PSD psd, MWCOORD x, MWCOORD y, PMWIMAGEHDR pimage)
517
{
518
  MWCOORD minx;
519
  MWCOORD maxx;
520
  MWUCHAR bitvalue = 0;
521
  int bitcount;
522
  MWUCHAR *imagebits;
523
  MWCOORD       height, width;
524
  MWPIXELVAL pixel;
525
  int clip;
526
  int extra, linesize;
527
  int   rgborder;
528
  MWCOLORVAL cr;
529
  MWCOORD yoff;
530
  unsigned long transcolor;
531
  MWPIXELVAL convtable[256];
532
 
533
  height = pimage->height;
534
  width = pimage->width;
535
 
536
  /* determine if entire image is clipped out, save clipresult for later*/
537
  clip = GdClipArea(psd, x, y, x + width - 1, y + height - 1);
538
  if(clip == CLIP_INVISIBLE)
539
        return;
540
 
541
  transcolor = pimage->transcolor;
542
 
543
  /*
544
   * Merge the images's palette and build a palette index conversion table.
545
   */
546
  if (pimage->bpp <= 8) {
547
        if(!pimage->palette) {
548
                /* for jpeg's without a palette*/
549
                for(yoff=0; yoff<pimage->palsize; ++yoff)
550
                        convtable[yoff] = yoff;
551
        } else GdMakePaletteConversionTable(psd, pimage->palette,
552
                pimage->palsize, convtable, MERGEPALETTE);
553
 
554
        /* The following is no longer used.  One reason is that it required */
555
        /* the transparent color to be unique, which was unnessecary        */
556
 
557
        /* convert transcolor to converted palette index for speed*/
558
        /* if (transcolor != -1L)
559
           transcolor = (unsigned long) convtable[transcolor];  */
560
  }
561
 
562
  minx = x;
563
  maxx = x + width - 1;
564
  imagebits = pimage->imagebits;
565
 
566
  /* check for bottom-up image*/
567
  if(pimage->compression & MWIMAGE_UPSIDEDOWN) {
568
        y += height - 1;
569
        yoff = -1;
570
  } else
571
        yoff = 1;
572
 
573
#define PIX2BYTES(n)    (((n)+7)/8)
574
  /* imagebits are dword aligned*/
575
  switch(pimage->bpp) {
576
  default:
577
  case 8:
578
        linesize = width;
579
        break;
580
  case 32:
581
        linesize = width*4;
582
        break;
583
  case 24:
584
        linesize = width*3;
585
        break;
586
  case 4:
587
        linesize = PIX2BYTES(width<<2);
588
        break;
589
  case 1:
590
        linesize = PIX2BYTES(width);
591
        break;
592
  }
593
  extra = pimage->pitch - linesize;
594
 
595
  /* 24bpp RGB rather than BGR byte order?*/
596
  rgborder = pimage->compression & MWIMAGE_RGB;
597
 
598
  bitcount = 0;
599
  while(height > 0) {
600
        unsigned long trans = 0;
601
 
602
        if (bitcount <= 0) {
603
                bitcount = sizeof(MWUCHAR) * 8;
604
                bitvalue = *imagebits++;
605
        }
606
        switch(pimage->bpp) {
607
        case 24:
608
        case 32:
609
                cr = rgborder? MWRGB(bitvalue, imagebits[0], imagebits[1]):
610
                        MWRGB(imagebits[1], imagebits[0], bitvalue);
611
 
612
                /* Include the upper bits for transcolor stuff */
613
                if (imagebits[2])       /* FIXME: 24bpp error*/
614
                    trans = cr | 0x01000000L;
615
 
616
                if (pimage->bpp == 32)
617
                        imagebits += 3;
618
                else imagebits += 2;
619
                bitcount = 0;
620
 
621
                /* handle transparent color*/
622
                if (transcolor == trans)
623
                    goto next;
624
 
625
                switch(psd->pixtype) {
626
                case MWPF_PALETTE:
627
                default:
628
                        pixel = GdFindColor(cr);
629
                        break;
630
                case MWPF_TRUECOLOR0888:
631
                case MWPF_TRUECOLOR888:
632
                        pixel = COLOR2PIXEL888(cr);
633
                        break;
634
                case MWPF_TRUECOLOR565:
635
                        pixel = COLOR2PIXEL565(cr);
636
                        break;
637
                case MWPF_TRUECOLOR555:
638
                        pixel = COLOR2PIXEL555(cr);
639
                        break;
640
                case MWPF_TRUECOLOR332:
641
                        pixel = COLOR2PIXEL332(cr);
642
                        break;
643
                }
644
                break;
645
        default:
646
        case 8:
647
          bitcount = 0;
648
          if (bitvalue == transcolor)
649
              goto next;
650
 
651
          pixel = convtable[bitvalue];
652
          break;
653
        case 4:
654
          if (((bitvalue & 0xf0) >> 4) == transcolor) {
655
               bitvalue <<= 4;
656
               bitcount -= 4;
657
               goto next;
658
          }
659
 
660
          pixel = convtable[(bitvalue & 0xf0) >> 4];
661
          bitvalue <<= 4;
662
          bitcount -= 4;
663
          break;
664
        case 1:
665
          --bitcount;
666
          if (((bitvalue & 0x80) ? 1 : 0) == transcolor) {
667
              bitvalue <<= 1;
668
              goto next;
669
            }
670
 
671
          pixel = convtable[(bitvalue & 0x80)? 1: 0];
672
          bitvalue <<= 1;
673
          break;
674
        }
675
 
676
        /* if((unsigned long)pixel != transcolor &&*/
677
        if (clip == CLIP_VISIBLE || GdClipPoint(psd, x, y))
678
            psd->DrawPixel(psd, x, y, pixel);
679
#if 0
680
        /* fix: use clipmaxx to clip quicker*/
681
        else if(clip != CLIP_VISIBLE && !clipresult && x > clipmaxx) {
682
                x = maxx;
683
        }
684
#endif
685
next:
686
        if(x++ == maxx) {
687
                x = minx;
688
                y += yoff;
689
                height--;
690
                bitcount = 0;
691
                imagebits += extra;
692
        }
693
  }
694
  GdFixCursor(psd);
695
}
696
 
697
/*
698
 * Read a rectangular area of the screen.
699
 * The color table is indexed row by row.
700
 */
701
void
702
GdReadArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
703
        MWPIXELVAL *pixels)
704
{
705
        MWCOORD                 row;
706
        MWCOORD                 col;
707
 
708
        if (width <= 0 || height <= 0)
709
                return;
710
 
711
        GdCheckCursor(psd, x, y, x+width-1, y+height-1);
712
        for (row = y; row < height+y; row++)
713
                for (col = x; col < width+x; col++)
714
                        if (row < 0 || row >= psd->yvirtres ||
715
                            col < 0 || col >= psd->xvirtres)
716
                                *pixels++ = 0;
717
                        else *pixels++ = psd->ReadPixel(psd, col, row);
718
 
719
        GdFixCursor(psd);
720
}
721
 
722
/* Draw a rectangle of color values, clipping if necessary.
723
 * If a color matches the background color,
724
 * then that pixel is only drawn if the gr_usebg flag is set.
725
 *
726
 * The pixels are packed according to pixtype:
727
 *
728
 * pixtype              array of
729
 * MWPF_RGB             MWCOLORVAL (unsigned long)
730
 * MWPF_PIXELVAL        MWPIXELVAL (compile-time dependent)
731
 * MWPF_PALETTE         unsigned char
732
 * MWPF_TRUECOLOR0888   unsigned long
733
 * MWPF_TRUECOLOR888    packed struct {char r,char g,char b} (24 bits)
734
 * MWPF_TRUECOLOR565    unsigned short
735
 * MWPF_TRUECOLOR555    unsigned short
736
 * MWPF_TRUECOLOR332    unsigned char
737
 *
738
 * NOTE: Currently, no translation is performed if the pixtype
739
 * is not MWPF_RGB.  Pixtype is only then used to determine the
740
 * packed size of the pixel data, and is then stored unmodified
741
 * in a MWPIXELVAL and passed to the screen driver.  Virtually,
742
 * this means there's only three reasonable options for client
743
 * programs: (1) pass all data as RGB MWCOLORVALs, (2) pass
744
 * data as unpacked 32-bit MWPIXELVALs in the format the current
745
 * screen driver is running, or (3) pass data as packed values
746
 * in the format the screen driver is running.  Options 2 and 3
747
 * are identical except for the packing structure.
748
 */
749
void
750
GdArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height, void *pixels,
751
        int pixtype)
752
{
753
        unsigned char *PIXELS = pixels; /* for ANSI compilers, can't use void*/
754
        long cellstodo;                 /* remaining number of cells */
755
        long count;                     /* number of cells of same color */
756
        long cc;                        /* current cell count */
757
        long rows;                      /* number of complete rows */
758
        MWCOORD minx;                   /* minimum x value */
759
        MWCOORD maxx;                   /* maximum x value */
760
        MWPIXELVAL savecolor;           /* saved foreground color */
761
        MWBOOL dodraw;                  /* TRUE if draw these points */
762
        MWCOLORVAL rgbcolor = 0L;
763
        int pixsize;
764
        unsigned char r, g, b;
765
 
766
        minx = x;
767
        maxx = x + width - 1;
768
 
769
        /* Set up area clipping, and just return if nothing is visible */
770
        if ( GdClipArea(psd, minx, y, maxx, y + height - 1) == CLIP_INVISIBLE )
771
                return;
772
 
773
/* psd->DrawArea driver call temp removed, doesn't work with new blit routines*/
774
#if 0000
775
{
776
        driver_gc_t hwgc;
777
        int px1, px2, py1, py2, pw, ph, rx1, rx2, ry1, ry2;
778
#if DYNAMICREGIONS
779
        MWRECT *prc;
780
        extern MWCLIPREGION *clipregion;
781
#else
782
        MWCLIPRECT *prc;
783
        extern MWCLIPRECT cliprects[];
784
        extern int clipcount;
785
#endif
786
 
787
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
788
        /* can't use drawarea driver in 16 bpp mode yet with font routines*/
789
        goto fallback;
790
#endif
791
        if ( !(psd->flags & PSF_HAVEOP_COPY) )
792
                goto fallback;
793
 
794
#if DYNAMICREGIONS
795
        prc = clipregion->rects;
796
        count = clipregion->numRects;
797
#else
798
        prc = cliprects;
799
        count = clipcount;
800
#endif
801
 
802
        hwgc.pixels = PIXELS;
803
        hwgc.src_linelen = width;
804
        hwgc.gr_usebg = gr_usebg;
805
        hwgc.bg_color = gr_background;
806
 
807
        while ( count-- > 0 ) {
808
#if DYNAMICREGIONS
809
                rx1 = prc->left;
810
                ry1 = prc->top;
811
                rx2 = prc->right;
812
                ry2 = prc->bottom;
813
#else
814
                /* New clip-code by Morten */
815
                rx1 = prc->x;
816
                ry1 = prc->y;
817
                rx2 = prc->x + prc->width;
818
                ry2 = prc->y + prc->height;
819
#endif
820
 
821
                /* Check if this rect intersects with the one we draw */
822
                px1 = x;
823
                py1 = y;
824
                px2 = x + width;
825
                py2 = y + height;
826
                if ( px1 < rx1 ) px1 = rx1;
827
                if ( py1 < ry1 ) py1 = ry1;
828
                if ( px2 > rx2 ) px2 = rx2;
829
                if ( py2 > ry2 ) py2 = ry2;
830
 
831
                pw = px2 - px1;
832
                ph = py2 - py1;
833
 
834
                if ( pw > 0 && ph > 0 ) {
835
                        hwgc.dstx = px1;
836
                        hwgc.dsty = py1;
837
                        hwgc.dstw = pw;
838
                        hwgc.dsth = ph;
839
                        hwgc.srcx = px1 - x;
840
                        hwgc.srcy = py1 - y;
841
                        GdCheckCursor(psd,px1,py1,px1+pw-1,py1+ph-1);
842
                        psd->DrawArea(psd,&hwgc,PSDOP_COPY);
843
                }
844
                prc++;
845
        }
846
        GdFixCursor(psd);
847
        return;
848
 fallback:
849
}
850
#endif /* if 0000 temp removed*/
851
 
852
        /* Calculate size of packed pixels*/
853
        switch(pixtype) {
854
        case MWPF_RGB:
855
                pixsize = sizeof(MWCOLORVAL);
856
                break;
857
        case MWPF_PIXELVAL:
858
                pixsize = sizeof(MWPIXELVAL);
859
                break;
860
        case MWPF_PALETTE:
861
        case MWPF_TRUECOLOR332:
862
                pixsize = sizeof(unsigned char);
863
                break;
864
        case MWPF_TRUECOLOR0888:
865
                pixsize = sizeof(unsigned long);
866
                break;
867
        case MWPF_TRUECOLOR888:
868
                pixsize = 3;
869
                break;
870
        case MWPF_TRUECOLOR565:
871
        case MWPF_TRUECOLOR555:
872
                pixsize = sizeof(unsigned short);
873
                break;
874
        default:
875
                return;
876
        }
877
 
878
  savecolor = gr_foreground;
879
  cellstodo = (long)width * height;
880
  while (cellstodo > 0) {
881
        /* read the pixel value from the pixtype*/
882
        switch(pixtype) {
883
        case MWPF_RGB:
884
                rgbcolor = *(MWCOLORVAL *)PIXELS;
885
                PIXELS += sizeof(MWCOLORVAL);
886
                gr_foreground = GdFindColor(rgbcolor);
887
                break;
888
        case MWPF_PIXELVAL:
889
                gr_foreground = *(MWPIXELVAL *)PIXELS;
890
                PIXELS += sizeof(MWPIXELVAL);
891
                break;
892
        case MWPF_PALETTE:
893
        case MWPF_TRUECOLOR332:
894
                gr_foreground = *PIXELS++;
895
                break;
896
        case MWPF_TRUECOLOR0888:
897
                gr_foreground = *(unsigned long *)PIXELS;
898
                PIXELS += sizeof(unsigned long);
899
                break;
900
        case MWPF_TRUECOLOR888:
901
                r = *PIXELS++;
902
                g = *PIXELS++;
903
                b = *PIXELS++;
904
                gr_foreground = (MWPIXELVAL)MWRGB(r, g, b);
905
                break;
906
        case MWPF_TRUECOLOR565:
907
        case MWPF_TRUECOLOR555:
908
                gr_foreground = *(unsigned short *)PIXELS;
909
                PIXELS += sizeof(unsigned short);
910
                break;
911
        }
912
        dodraw = (gr_usebg || (gr_foreground != gr_background));
913
        count = 1;
914
        --cellstodo;
915
 
916
        /* See how many of the adjacent remaining points have the
917
         * same color as the next point.
918
         *
919
         * NOTE: Yes, with the addition of the pixel unpacking,
920
         * it's almost slower to look ahead than to just draw
921
         * the pixel...  FIXME
922
         */
923
        while (cellstodo > 0) {
924
                switch(pixtype) {
925
                case MWPF_RGB:
926
                        if(rgbcolor != *(MWCOLORVAL *)PIXELS)
927
                                goto breakwhile;
928
                        PIXELS += sizeof(MWCOLORVAL);
929
                        break;
930
                case MWPF_PIXELVAL:
931
                        if(gr_foreground != *(MWPIXELVAL *)PIXELS)
932
                                goto breakwhile;
933
                        PIXELS += sizeof(MWPIXELVAL);
934
                        break;
935
                case MWPF_PALETTE:
936
                case MWPF_TRUECOLOR332:
937
                        if(gr_foreground != *(unsigned char *)PIXELS)
938
                                goto breakwhile;
939
                        ++PIXELS;
940
                        break;
941
                case MWPF_TRUECOLOR0888:
942
                        if(gr_foreground != *(unsigned long *)PIXELS)
943
                                goto breakwhile;
944
                        PIXELS += sizeof(unsigned long);
945
                        break;
946
                case MWPF_TRUECOLOR888:
947
                        r = *(unsigned char *)PIXELS;
948
                        g = *(unsigned char *)(PIXELS + 1);
949
                        b = *(unsigned char *)(PIXELS + 2);
950
                        if(gr_foreground != (MWPIXELVAL)MWRGB(r, g, b))
951
                                goto breakwhile;
952
                        PIXELS += 3;
953
                        break;
954
                case MWPF_TRUECOLOR565:
955
                case MWPF_TRUECOLOR555:
956
                        if(gr_foreground != *(unsigned short *)PIXELS)
957
                                goto breakwhile;
958
                        PIXELS += sizeof(unsigned short);
959
                        break;
960
                }
961
                ++count;
962
                --cellstodo;
963
        }
964
breakwhile:
965
 
966
        /* If there is only one point with this color, then draw it
967
         * by itself.
968
         */
969
        if (count == 1) {
970
                if (dodraw)
971
                        drawpoint(psd, x, y);
972
                if (++x > maxx) {
973
                        x = minx;
974
                        y++;
975
                }
976
                continue;
977
        }
978
 
979
        /* There are multiple points with the same color. If we are
980
         * not at the start of a row of the rectangle, then draw this
981
         * first row specially.
982
         */
983
        if (x != minx) {
984
                cc = count;
985
                if (x + cc - 1 > maxx)
986
                        cc = maxx - x + 1;
987
                if (dodraw)
988
                        drawrow(psd, x, x + cc - 1, y);
989
                count -= cc;
990
                x += cc;
991
                if (x > maxx) {
992
                        x = minx;
993
                        y++;
994
                }
995
        }
996
 
997
        /* Now the x value is at the beginning of a row if there are
998
         * any points left to be drawn.  Draw all the complete rows
999
         * with one call.
1000
         */
1001
        rows = count / width;
1002
        if (rows > 0) {
1003
                if (dodraw) {
1004
                        /* note: change to fillrect, (parm types changed)*/
1005
                        /*GdFillRect(psd, x, y, maxx, y + rows - 1);*/
1006
                        GdFillRect(psd, x, y, maxx - x + 1, rows);
1007
                }
1008
                count %= width;
1009
                y += rows;
1010
        }
1011
 
1012
        /* If there is a final partial row of pixels left to be
1013
         * drawn, then do that.
1014
         */
1015
        if (count > 0) {
1016
                if (dodraw)
1017
                        drawrow(psd, x, x + count - 1, y);
1018
                x += count;
1019
        }
1020
  }
1021
  gr_foreground = savecolor;
1022
  GdFixCursor(psd);
1023
}
1024
 
1025
#if NOTYET
1026
/* Copy a rectangular area from one screen area to another.
1027
 * This bypasses clipping.
1028
 */
1029
void
1030
GdCopyArea(PSD psd, MWCOORD srcx, MWCOORD srcy, MWCOORD width, MWCOORD height,
1031
        MWCOORD destx, MWCOORD desty)
1032
{
1033
        if (width <= 0 || height <= 0)
1034
                return;
1035
 
1036
        if (srcx == destx && srcy == desty)
1037
                return;
1038
        GdCheckCursor(psd, srcx, srcy, srcx + width - 1, srcy + height - 1);
1039
        GdCheckCursor(psd, destx, desty, destx + width - 1, desty + height - 1);
1040
        psd->CopyArea(psd, srcx, srcy, width, height, destx, desty);
1041
        GdFixCursor(psd);
1042
}
1043
#endif
1044
 
1045
/* Copy source rectangle of pixels to destination rectangle quickly*/
1046
void
1047
GdBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD width, MWCOORD height,
1048
        PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long rop)
1049
{
1050
        int rx1, rx2, ry1, ry2;
1051
        int px1, px2, py1, py2;
1052
        int pw, ph;
1053
        int count;
1054
#if DYNAMICREGIONS
1055
        MWRECT *        prc;
1056
        extern MWCLIPREGION *clipregion;
1057
#else
1058
        MWCLIPRECT *    prc;
1059
        extern MWCLIPRECT cliprects[];
1060
        extern int clipcount;
1061
#endif
1062
 
1063
        /*FIXME: compare bpp's and convert if necessary*/
1064
        assert(dstpsd->planes == srcpsd->planes);
1065
        assert(dstpsd->bpp == srcpsd->bpp);
1066
 
1067
        /* temporary assert() until rotation blits completed*/
1068
        assert(dstpsd->portrait == srcpsd->portrait);
1069
 
1070
        /* clip blit rectangle to source screen/bitmap size*/
1071
        /* we must do this because there isn't any source clipping setup*/
1072
        if(srcx < 0) {
1073
                width += srcx;
1074
                dstx -= srcx;
1075
                srcx = 0;
1076
        }
1077
        if(srcy < 0) {
1078
                height += srcy;
1079
                dsty -= srcy;
1080
                srcy = 0;
1081
        }
1082
        if(srcx+width > srcpsd->xvirtres)
1083
                width = srcpsd->xvirtres - srcx;
1084
        if(srcy+height > srcpsd->yvirtres)
1085
                height = srcpsd->yvirtres - srcy;
1086
 
1087
        switch(GdClipArea(dstpsd, dstx, dsty, dstx+width-1, dsty+height-1)) {
1088
        case CLIP_VISIBLE:
1089
                /* check cursor in src region*/
1090
                GdCheckCursor(dstpsd, srcx, srcy, srcx+width-1, srcy+height-1);
1091
                dstpsd->Blit(dstpsd, dstx, dsty, width, height,
1092
                        srcpsd, srcx, srcy, rop);
1093
                GdFixCursor(dstpsd);
1094
                return;
1095
 
1096
        case CLIP_INVISIBLE:
1097
                return;
1098
        }
1099
 
1100
        /* Partly clipped, we'll blit using destination clip
1101
         * rectangles, and offset the blit accordingly.
1102
         * Since the destination is already clipped, we
1103
         * only need to clip the source here.
1104
         */
1105
#if DYNAMICREGIONS
1106
        prc = clipregion->rects;
1107
        count = clipregion->numRects;
1108
#else
1109
        prc = cliprects;
1110
        count = clipcount;
1111
#endif
1112
        while(--count >= 0) {
1113
#if DYNAMICREGIONS
1114
                rx1 = prc->left;
1115
                ry1 = prc->top;
1116
                rx2 = prc->right;
1117
                ry2 = prc->bottom;
1118
#else
1119
                rx1 = prc->x;
1120
                ry1 = prc->y;
1121
                rx2 = prc->x + prc->width;
1122
                ry2 = prc->y + prc->height;
1123
#endif
1124
                /* Check:  does this rect intersect the one we want to draw? */
1125
                px1 = dstx;
1126
                py1 = dsty;
1127
                px2 = dstx + width;
1128
                py2 = dsty + height;
1129
                if (px1 < rx1) px1 = rx1;
1130
                if (py1 < ry1) py1 = ry1;
1131
                if (px2 > rx2) px2 = rx2;
1132
                if (py2 > ry2) py2 = ry2;
1133
 
1134
                pw = px2 - px1;
1135
                ph = py2 - py1;
1136
                if(pw > 0 && ph > 0) {
1137
                        /* check cursor in dest and src regions*/
1138
                        GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
1139
                        GdCheckCursor(dstpsd, srcx, srcy,
1140
                                srcx+width, srcy+height);
1141
                        dstpsd->Blit(dstpsd, px1, py1, pw, ph, srcpsd,
1142
                                srcx + (px1-dstx), srcy + (py1-dsty), rop);
1143
                }
1144
                ++prc;
1145
        }
1146
        GdFixCursor(dstpsd);
1147
}
1148
 
1149
/* experimental globals for ratio bug when src != 0*/
1150
int g_row_inc, g_col_inc;
1151
/* Stretch source rectangle of pixels to destination rectangle quickly*/
1152
void
1153
GdStretchBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
1154
        MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
1155
        MWCOORD srch, long rop)
1156
{
1157
        int count;
1158
#if DYNAMICREGIONS
1159
        MWRECT *        prc;
1160
        extern MWCLIPREGION *clipregion;
1161
#else
1162
        MWCLIPRECT *    prc;
1163
        extern MWCLIPRECT cliprects[];
1164
        extern int clipcount;
1165
#endif
1166
 
1167
g_row_inc = g_col_inc = 0;
1168
 
1169
        /* check for driver stretch blit implementation*/
1170
        if (!dstpsd->StretchBlit)
1171
                return;
1172
 
1173
        /*FIXME: compare bpp's and convert if necessary*/
1174
        assert(dstpsd->planes == srcpsd->planes);
1175
        assert(dstpsd->bpp == srcpsd->bpp);
1176
 
1177
        /* clip blit rectangle to source screen/bitmap size*/
1178
        /* we must do this because there isn't any source clipping setup*/
1179
        if(srcx < 0) {
1180
                srcw += srcx;
1181
                /*dstx -= srcx;*/
1182
                srcx = 0;
1183
        }
1184
        if(srcy < 0) {
1185
                srch += srcy;
1186
                /*dsty -= srcy;*/
1187
                srcy = 0;
1188
        }
1189
        if(srcx+srcw > srcpsd->xvirtres)
1190
                srcw = srcpsd->xvirtres - srcx;
1191
        if(srcy+srch > srcpsd->yvirtres)
1192
                srch = srcpsd->yvirtres - srcy;
1193
 
1194
        /* temp dest clipping for partially visible case*/
1195
        if(dstx+dstw > dstpsd->xvirtres)
1196
                dstw = dstpsd->xvirtres - dstx;
1197
        if(dsty+dsth > dstpsd->yvirtres)
1198
                dsth = dstpsd->yvirtres - dsty;
1199
 
1200
        switch(GdClipArea(dstpsd, dstx, dsty, dstx+dstw-1, dsty+dsth-1)) {
1201
        case CLIP_VISIBLE:
1202
                /* check cursor in src region*/
1203
                GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw-1, srcy+srch-1);
1204
                dstpsd->StretchBlit(dstpsd, dstx, dsty, dstw, dsth,
1205
                        srcpsd, srcx, srcy, srcw, srch, rop);
1206
                GdFixCursor(dstpsd);
1207
                return;
1208
 
1209
        case CLIP_INVISIBLE:
1210
                return;
1211
        }
1212
 
1213
        /* Partly clipped, we'll blit using destination clip
1214
         * rectangles, and offset the blit accordingly.
1215
         * Since the destination is already clipped, we
1216
         * only need to clip the source here.
1217
         */
1218
#if DYNAMICREGIONS
1219
        prc = clipregion->rects;
1220
        count = clipregion->numRects;
1221
#else
1222
        prc = cliprects;
1223
        count = clipcount;
1224
#endif
1225
        while(--count >= 0) {
1226
                int rx1, rx2, ry1, ry2;
1227
                int px1, px2, py1, py2;
1228
                int pw, ph;
1229
                int sx, sy, sw, sh;
1230
#if DYNAMICREGIONS
1231
                rx1 = prc->left;
1232
                ry1 = prc->top;
1233
                rx2 = prc->right;
1234
                ry2 = prc->bottom;
1235
#else
1236
                rx1 = prc->x;
1237
                ry1 = prc->y;
1238
                rx2 = prc->x + prc->width;
1239
                ry2 = prc->y + prc->height;
1240
#endif
1241
                /* Check:  does this rect intersect the one we want to draw? */
1242
                px1 = dstx;
1243
                py1 = dsty;
1244
                px2 = dstx + dstw;
1245
                py2 = dsty + dsth;
1246
                if (px1 < rx1) px1 = rx1;
1247
                if (py1 < ry1) py1 = ry1;
1248
                if (px2 > rx2) px2 = rx2;
1249
                if (py2 > ry2) py2 = ry2;
1250
 
1251
                pw = px2 - px1;
1252
                ph = py2 - py1;
1253
                if(pw > 0 && ph > 0) {
1254
                        /* calc proper src/dst offset for stretch rect*/
1255
g_row_inc = (srch << 16) / dsth;
1256
g_col_inc = (srcw << 16) / dstw;
1257
                        sw = pw * srcw / dstw;
1258
                        sh = ph * srch / dsth;
1259
 
1260
                        if (sw > 0 && sh > 0) {
1261
                                sx = srcx + (px1-dstx) * srcw / dstw;
1262
                                sy = srcy + (py1-dsty) * srch / dsth;
1263
/*printf("P %d,%d,%d,%d   %d,%d\n", sx, sy, sw, sh, g_row_inc, g_col_inc);*/
1264
 
1265
                                /* check cursor in dest and src regions*/
1266
                                GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
1267
                                GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw, srcy+srch);
1268
                                dstpsd->StretchBlit(dstpsd, px1, py1, pw, ph, srcpsd,
1269
                                        sx, sy, sw, sh, rop);
1270
                        }
1271
                }
1272
                ++prc;
1273
        }
1274
        GdFixCursor(dstpsd);
1275
}
1276
 
1277
/*
1278
 * Calculate size and linelen of memory gc.
1279
 * If bpp or planes is 0, use passed psd's bpp/planes.
1280
 * Note: linelen is calculated to be DWORD aligned for speed
1281
 * for bpp <= 8.  Linelen is converted to bytelen for bpp > 8.
1282
 */
1283
int
1284
GdCalcMemGCAlloc(PSD psd, unsigned int width, unsigned int height, int planes,
1285
        int bpp, int *psize, int *plinelen)
1286
{
1287
        int     bytelen, linelen, tmp;
1288
 
1289
        if(!planes)
1290
                planes = psd->planes;
1291
        if(!bpp)
1292
                bpp = psd->bpp;
1293
        /*
1294
         * swap width and height in left/right portrait modes,
1295
         * so imagesize is calculated properly
1296
         */
1297
        if(psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT)) {
1298
                tmp = width;
1299
                width = height;
1300
                height = tmp;
1301
        }
1302
 
1303
        /*
1304
         * use bpp and planes to create size and linelen.
1305
         * linelen is in bytes for bpp 1, 2, 4, 8, and pixels for bpp 16,24,32.
1306
         */
1307
        if(planes == 1) {
1308
                switch(bpp) {
1309
                case 1:
1310
                        linelen = (width+7)/8;
1311
                        bytelen = linelen = (linelen+3) & ~3;
1312
                        break;
1313
                case 2:
1314
                        linelen = (width+3)/4;
1315
                        bytelen = linelen = (linelen+3) & ~3;
1316
                        break;
1317
                case 4:
1318
                        linelen = (width+1)/2;
1319
                        bytelen = linelen = (linelen+3) & ~3;
1320
                        break;
1321
                case 8:
1322
                        bytelen = linelen = (width+3) & ~3;
1323
                        break;
1324
                case 16:
1325
                        linelen = width;
1326
                        bytelen = width * 2;
1327
                        break;
1328
                case 24:
1329
                        linelen = width;
1330
                        bytelen = width * 3;
1331
                        break;
1332
                case 32:
1333
                        linelen = width;
1334
                        bytelen = width * 4;
1335
                        break;
1336
                default:
1337
                        return 0;
1338
                }
1339
        } else if(planes == 4) {
1340
                /* FIXME assumes VGA 4 planes 4bpp*/
1341
                /* we use 4bpp linear for memdc format*/
1342
                linelen = (width+1)/2;
1343
                linelen = (linelen+3) & ~3;
1344
                bytelen = linelen;
1345
        } else {
1346
                *psize = *plinelen = 0;
1347
                return 0;
1348
        }
1349
 
1350
        *plinelen = linelen;
1351
        *psize = bytelen * height;
1352
        return 1;
1353
}
1354
 
1355
/* Translate a rectangle of color values
1356
 *
1357
 * The pixels are packed according to inpixtype/outpixtype:
1358
 *
1359
 * pixtype              array of
1360
 * MWPF_RGB             MWCOLORVAL (unsigned long)
1361
 * MWPF_PIXELVAL        MWPIXELVAL (compile-time dependent)
1362
 * MWPF_PALETTE         unsigned char
1363
 * MWPF_TRUECOLOR0888   unsigned long
1364
 * MWPF_TRUECOLOR888    packed struct {char r,char g,char b} (24 bits)
1365
 * MWPF_TRUECOLOR565    unsigned short
1366
 * MWPF_TRUECOLOR555    unsigned short
1367
 * MWPF_TRUECOLOR332    unsigned char
1368
 */
1369
void
1370
GdTranslateArea(MWCOORD width, MWCOORD height, void *in, int inpixtype,
1371
        MWCOORD inpitch, void *out, int outpixtype, int outpitch)
1372
{
1373
        unsigned char * inbuf = in;
1374
        unsigned char * outbuf = out;
1375
        unsigned long   pixelval;
1376
        MWCOLORVAL      colorval;
1377
        MWCOORD         x, y;
1378
        unsigned char   r, g, b;
1379
        extern MWPALENTRY gr_palette[256];
1380
        int       gr_palsize = 256;     /* FIXME*/
1381
 
1382
        for(y=0; y<height; ++y) {
1383
            for(x=0; x<width; ++x) {
1384
                /* read pixel value and convert to BGR colorval (0x00BBGGRR)*/
1385
                switch (inpixtype) {
1386
                case MWPF_RGB:
1387
                        colorval = *(MWCOLORVAL *)inbuf;
1388
                        inbuf += sizeof(MWCOLORVAL);
1389
                        break;
1390
                case MWPF_PIXELVAL:
1391
                        pixelval = *(MWPIXELVAL *)inbuf;
1392
                        inbuf += sizeof(MWPIXELVAL);
1393
                        /* convert based on compile-time MWPIXEL_FORMAT*/
1394
#if MWPIXEL_FORMAT == MWPF_PALETTE
1395
                        colorval = GETPALENTRY(gr_palette, pixelval);
1396
#else
1397
                        colorval = PIXELVALTOCOLORVAL(pixelval);
1398
#endif
1399
                        break;
1400
                case MWPF_PALETTE:
1401
                        pixelval = *inbuf++;
1402
                        colorval = GETPALENTRY(gr_palette, pixelval);
1403
                        break;
1404
                case MWPF_TRUECOLOR332:
1405
                        pixelval = *inbuf++;
1406
                        colorval = PIXEL332TOCOLORVAL(pixelval);
1407
                        break;
1408
                case MWPF_TRUECOLOR0888:
1409
                        pixelval = *(unsigned long *)inbuf;
1410
                        colorval = PIXEL888TOCOLORVAL(pixelval);
1411
                        inbuf += sizeof(unsigned long);
1412
                        break;
1413
                case MWPF_TRUECOLOR888:
1414
                        r = *inbuf++;
1415
                        g = *inbuf++;
1416
                        b = *inbuf++;
1417
                        colorval = (MWPIXELVAL)MWRGB(r, g, b);
1418
                        break;
1419
                case MWPF_TRUECOLOR565:
1420
                        pixelval = *(unsigned short *)inbuf;
1421
                        colorval = PIXEL565TOCOLORVAL(pixelval);
1422
                        inbuf += sizeof(unsigned short);
1423
                        break;
1424
                case MWPF_TRUECOLOR555:
1425
                        pixelval = *(unsigned short *)inbuf;
1426
                        colorval = PIXEL555TOCOLORVAL(pixelval);
1427
                        inbuf += sizeof(unsigned short);
1428
                        break;
1429
                default:
1430
                        return;
1431
                }
1432
 
1433
                /* convert from BGR colorval to desired output pixel format*/
1434
                switch (outpixtype) {
1435
                case MWPF_RGB:
1436
                        *(MWCOLORVAL *)outbuf = colorval;
1437
                        outbuf += sizeof(MWCOLORVAL);
1438
                        break;
1439
                case MWPF_PIXELVAL:
1440
                        /* convert based on compile-time MWPIXEL_FORMAT*/
1441
#if MWPIXEL_FORMAT == MWPF_PALETTE
1442
                        *(MWPIXELVAL *)outbuf = GdFindNearestColor(gr_palette,
1443
                                        gr_palsize, colorval);
1444
#else
1445
                        *(MWPIXELVAL *)outbuf = COLORVALTOPIXELVAL(colorval);
1446
#endif
1447
                        outbuf += sizeof(MWPIXELVAL);
1448
                        break;
1449
                case MWPF_PALETTE:
1450
                        *outbuf++ = GdFindNearestColor(gr_palette, gr_palsize,
1451
                                        colorval);
1452
                        break;
1453
                case MWPF_TRUECOLOR332:
1454
                        *outbuf++ = COLOR2PIXEL332(colorval);
1455
                        break;
1456
                case MWPF_TRUECOLOR0888:
1457
                        *(unsigned long *)outbuf = COLOR2PIXEL888(colorval);
1458
                        outbuf += sizeof(unsigned long);
1459
                        break;
1460
                case MWPF_TRUECOLOR888:
1461
                        *outbuf++ = REDVALUE(colorval);
1462
                        *outbuf++ = GREENVALUE(colorval);
1463
                        *outbuf++ = BLUEVALUE(colorval);
1464
                        break;
1465
                case MWPF_TRUECOLOR565:
1466
                        *(unsigned short *)outbuf = COLOR2PIXEL565(colorval);
1467
                        outbuf += sizeof(unsigned short);
1468
                        break;
1469
                case MWPF_TRUECOLOR555:
1470
                        *(unsigned short *)outbuf = COLOR2PIXEL555(colorval);
1471
                        outbuf += sizeof(unsigned short);
1472
                        break;
1473
                }
1474
            }
1475
 
1476
            /* adjust line widths, if necessary*/
1477
            if(inpitch > width)
1478
                    inbuf += inpitch - width;
1479
            if(outpitch > width)
1480
                    outbuf += outpitch - width;
1481
        }
1482
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.