~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to ilbm/ilbmimggblt.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/ilbm/ilbmimggblt.c,v 3.0 1996/08/18 01:53:57 dawes Exp $ */
 
2
/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */
 
3
/***********************************************************
 
4
 
 
5
Copyright (c) 1987  X Consortium
 
6
 
 
7
Permission is hereby granted, free of charge, to any person obtaining a copy
 
8
of this software and associated documentation files (the "Software"), to deal
 
9
in the Software without restriction, including without limitation the rights
 
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
11
copies of the Software, and to permit persons to whom the Software is
 
12
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 THE
 
20
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Except as contained in this notice, the name of the X Consortium shall not be
 
25
used in advertising or otherwise to promote the sale, use or other dealings
 
26
in this Software without prior written authorization from the X Consortium.
 
27
 
 
28
 
 
29
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
30
 
 
31
                        All Rights Reserved
 
32
 
 
33
Permission to use, copy, modify, and distribute this software and its
 
34
documentation for any purpose and without fee is hereby granted,
 
35
provided that the above copyright notice appear in all copies and that
 
36
both that copyright notice and this permission notice appear in
 
37
supporting documentation, and that the name of Digital not be
 
38
used in advertising or publicity pertaining to distribution of the
 
39
software without specific, written prior permission.
 
40
 
 
41
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
42
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
43
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
44
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
45
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
46
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
47
SOFTWARE.
 
48
 
 
49
******************************************************************/
 
50
/* $XConsortium: ilbmimggblt.c,v 5.17 94/04/17 20:28:25 dpw Exp $ */
 
51
 
 
52
/* Modified jun 95 by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
 
53
   to use interleaved bitplanes instead of normal bitplanes */
 
54
 
 
55
#ifdef HAVE_DIX_CONFIG_H
 
56
#include <dix-config.h>
 
57
#endif
 
58
 
 
59
#include                <X11/X.h>
 
60
#include                <X11/Xmd.h>
 
61
#include                <X11/Xproto.h>
 
62
#include                "ilbm.h"
 
63
#include                <X11/fonts/fontstruct.h>
 
64
#include                "dixfontstr.h"
 
65
#include                "gcstruct.h"
 
66
#include                "windowstr.h"
 
67
#include                "scrnintstr.h"
 
68
#include                "pixmapstr.h"
 
69
#include                "regionstr.h"
 
70
#include                "maskbits.h"
 
71
 
 
72
/*
 
73
        we should eventually special-case fixed-width fonts for ImageText.
 
74
 
 
75
        this works for fonts with glyphs <= 32 bits wide.
 
76
 
 
77
        the clipping calculations are done for worst-case fonts.
 
78
we make no assumptions about the heights, widths, or bearings
 
79
of the glyphs.  if we knew that the glyphs are all the same height,
 
80
we could clip the tops and bottoms per clipping box, rather
 
81
than per character per clipping box.  if we knew that the glyphs'
 
82
left and right bearings were wlle-behaved, we could clip a single
 
83
character at the start, output until the last unclipped
 
84
character, and then clip the last one.  this is all straightforward
 
85
to determine based on max-bounds and min-bounds from the font.
 
86
        there is some inefficiency introduced in the per-character
 
87
clipping to make what's going on clearer.
 
88
 
 
89
        (it is possible, for example, for a font to be defined in which the
 
90
next-to-last character in a font would be clipped out, but the last
 
91
one wouldn't.  the code below deals with this.)
 
92
 
 
93
        Image text looks at the bits in the glyph and the fg and bg in the
 
94
GC.  it paints a rectangle, as defined in the protocol dcoument,
 
95
and the paints the characters.
 
96
 
 
97
        the register allocations for startmask and endmask may not
 
98
be the right thing.  are there two other deserving candidates?
 
99
xoff, pdst, pglyph, and tmpSrc seem like the right things, though.
 
100
*/
 
101
 
 
102
void
 
103
ilbmImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
 
104
        DrawablePtr pDrawable;
 
105
        GC                              *pGC;
 
106
        int             x, y;
 
107
        unsigned int nglyph;
 
108
        CharInfoPtr *ppci;                              /* array of character info */
 
109
        pointer         pglyphBase;             /* start of array of glyphs */
 
110
{
 
111
        ExtentInfoRec info;             /* used by QueryGlyphExtents() */
 
112
        BoxRec bbox;            /* string's bounding box */
 
113
        xRectangle backrect;/* backing rectangle to paint.
 
114
                                                   in the general case, NOT necessarily
 
115
                                                   the same as the string's bounding box
 
116
                                                */
 
117
 
 
118
        CharInfoPtr pci;
 
119
        int xorg, yorg;         /* origin of drawable in bitmap */
 
120
        int widthDst;           /* width of dst in longwords */
 
121
 
 
122
                                                /* these keep track of the character origin */
 
123
        PixelType *pdstBase;
 
124
                                                /* points to longword with character origin */
 
125
        int xchar;                              /* xorigin of char (mod 32) */
 
126
 
 
127
                                                /* these are used for placing the glyph */
 
128
        register int xoff;              /* x offset of left edge of glyph (mod 32) */
 
129
        register PixelType *pdst;
 
130
                                                /* pointer to current longword in dst */
 
131
 
 
132
        register int d;
 
133
        int depthDst;
 
134
        int auxDst;
 
135
        int hSave;
 
136
        int w;                          /* width of glyph in bits */
 
137
        int h;                          /* height of glyph */
 
138
        int widthGlyph;         /* width of glyph, in bytes */
 
139
        unsigned char rrops[AFB_MAX_DEPTH];
 
140
        register unsigned char *pglyph;
 
141
                                                /* pointer to current row of glyph */
 
142
        unsigned char *pglyphSave;
 
143
 
 
144
                                                /* used for putting down glyph */
 
145
        register PixelType tmpSrc;
 
146
                                                /* for getting bits from glyph */
 
147
        register PixelType startmask;
 
148
        register PixelType endmask;
 
149
 
 
150
        register int nFirst;/* bits of glyph in current longword */
 
151
        PixelType *pdstSave;
 
152
        int oldFill;
 
153
        ilbmPrivGC *pPriv = (ilbmPrivGC *)(pGC->devPrivates[ilbmGCPrivateIndex].ptr);
 
154
 
 
155
        xorg = pDrawable->x;
 
156
        yorg = pDrawable->y;
 
157
        ilbmGetPixelWidthAuxDepthAndPointer(pDrawable, widthDst, auxDst, depthDst,
 
158
                                                                                                        pdstBase);
 
159
 
 
160
        QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
 
161
 
 
162
        backrect.x = x;
 
163
        backrect.y = y - FONTASCENT(pGC->font);
 
164
        backrect.width = info.overallWidth;
 
165
        backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
 
166
 
 
167
        x += xorg;
 
168
        y += yorg;
 
169
 
 
170
        bbox.x1 = x + info.overallLeft;
 
171
        bbox.x2 = x + info.overallRight;
 
172
        bbox.y1 = y - info.overallAscent;
 
173
        bbox.y2 = y + info.overallDescent;
 
174
 
 
175
        oldFill = pGC->fillStyle;
 
176
        pGC->fillStyle = FillSolid;
 
177
        ilbmReduceRop (pGC->alu, pGC->bgPixel, pGC->planemask, pGC->depth,
 
178
                                  pPriv->rrops);
 
179
        ilbmPolyFillRect(pDrawable, pGC, 1, &backrect);
 
180
        pGC->fillStyle = oldFill;
 
181
        ilbmReduceRop (pGC->alu, pGC->fgPixel, pGC->planemask, pGC->depth,
 
182
                                  pPriv->rrops);
 
183
        ilbmReduceRop (GXcopy, pGC->fgPixel, pGC->planemask, pGC->depth, rrops);
 
184
 
 
185
        /* the faint-hearted can open their eyes now */
 
186
 
 
187
        switch (RECT_IN_REGION(pGC->pScreen, pGC->pCompositeClip, &bbox)) {
 
188
                case rgnOUT:
 
189
                        break;
 
190
                case rgnIN:
 
191
                        pdstBase = ilbmScanlineNoBankSwitch(pdstBase, x, y, auxDst);
 
192
                        xchar = x & PIM;
 
193
 
 
194
                        while (nglyph--) {
 
195
                                pci = *ppci;
 
196
                                pglyphSave = FONTGLYPHBITS(pglyphBase, pci);
 
197
                                w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
 
198
                                hSave = pci->metrics.ascent + pci->metrics.descent;
 
199
                                widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
 
200
                                /* start at top scanline of glyph */
 
201
                                pdstSave = ilbmScanlineDelta(pdstBase, -pci->metrics.ascent,
 
202
                                                                                                          auxDst);
 
203
 
 
204
                                /* find correct word in scanline and x offset within it
 
205
                                   for left edge of glyph
 
206
                                */
 
207
                                xoff = xchar + pci->metrics.leftSideBearing;
 
208
                                if (xoff > PLST) {
 
209
                                        pdstSave++;
 
210
                                        xoff &= PIM;
 
211
                                } else if (xoff < 0) {
 
212
                                        xoff += PPW;
 
213
                                        pdstSave--;
 
214
                                }
 
215
 
 
216
                                for (d = 0; d < depthDst; d++) {
 
217
                                        h = hSave;
 
218
                                        pdst = pdstSave;
 
219
                                        pdstSave += widthDst;   /* @@@ NEXT PLANE @@@ */
 
220
                                        pglyph = pglyphSave;
 
221
 
 
222
                                        if ((xoff + w) <= PPW) {
 
223
                                                /* glyph all in one longword */
 
224
                                                maskpartialbits(xoff, w, startmask);
 
225
 
 
226
                                                switch (rrops[d]) {
 
227
                                                        case RROP_BLACK:
 
228
                                                                while (h--) {
 
229
                                                                        getleftbits(pglyph, w, tmpSrc);
 
230
                                                                        *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask);
 
231
                                                                        pglyph += widthGlyph;
 
232
                                                                        ilbmScanlineInc(pdst, auxDst);
 
233
                                                                }
 
234
                                                                break;
 
235
                                                        case RROP_WHITE:
 
236
                                                                while (h--) {
 
237
                                                                        getleftbits(pglyph, w, tmpSrc);
 
238
                                                                        *pdst |= SCRRIGHT(tmpSrc, xoff) & startmask;
 
239
                                                                        pglyph += widthGlyph;
 
240
                                                                        ilbmScanlineInc(pdst, auxDst);
 
241
                                                                }
 
242
                                                                break;
 
243
                                                        case RROP_NOP:
 
244
                                                                break;
 
245
                                                }
 
246
                                        } else {
 
247
                                                /* glyph crosses longword boundary */
 
248
                                                maskPPWbits(xoff, w, startmask, endmask);
 
249
                                                nFirst = PPW - xoff;
 
250
 
 
251
                                                switch (rrops[d]) {
 
252
                                                        case RROP_BLACK:
 
253
                                                                while (h--) {
 
254
                                                                        getleftbits(pglyph, w, tmpSrc);
 
255
                                                                        *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask);
 
256
                                                                        *(pdst+1) &= ~(SCRLEFT(tmpSrc, nFirst) & endmask);
 
257
                                                                        pglyph += widthGlyph;
 
258
                                                                        ilbmScanlineInc(pdst, auxDst);
 
259
                                                                }
 
260
                                                                break;
 
261
                                                        case RROP_WHITE:
 
262
                                                                while (h--) {
 
263
                                                                        getleftbits(pglyph, w, tmpSrc);
 
264
                                                                        *pdst |= SCRRIGHT(tmpSrc, xoff) & startmask;
 
265
                                                                        *(pdst+1) |= SCRLEFT(tmpSrc, nFirst) & endmask;
 
266
                                                                        pglyph += widthGlyph;
 
267
                                                                        ilbmScanlineInc(pdst, auxDst);
 
268
                                                                }
 
269
                                                                break;
 
270
                                                        case RROP_NOP:
 
271
                                                                break;
 
272
                                                }
 
273
                                        } /* glyph crosses longwords boundary */
 
274
                                } /* depth loop */
 
275
                                /* update character origin */
 
276
                                x += pci->metrics.characterWidth;
 
277
                                xchar += pci->metrics.characterWidth;
 
278
                                if (xchar > PLST) {
 
279
                                        xchar -= PPW;
 
280
                                        pdstBase++;
 
281
                                } else if (xchar < 0) {
 
282
                                        xchar += PPW;
 
283
                                        pdstBase--;
 
284
                                }
 
285
                                ppci++;
 
286
                        } /* while nglyph-- */
 
287
                        break;
 
288
                case rgnPART:
 
289
                        {
 
290
                                ilbmTEXTPOS *ppos;
 
291
                                int nbox;
 
292
                                BoxPtr pbox;
 
293
                                RegionPtr cclip;
 
294
                                int xpos;                               /* x position of char origin */
 
295
                                int i;
 
296
                                BoxRec clip;
 
297
                                int leftEdge, rightEdge;
 
298
                                int topEdge, bottomEdge;
 
299
                                int glyphRow;                           /* first row of glyph not wholly
 
300
                                                                                   clipped out */
 
301
                                int glyphCol;                           /* leftmost visible column of glyph */
 
302
                                int getWidth;                           /* bits to get from glyph */
 
303
 
 
304
                                if (!(ppos = (ilbmTEXTPOS *)ALLOCATE_LOCAL(nglyph *
 
305
                                                                                                                                                 sizeof(ilbmTEXTPOS))))
 
306
                                        return;
 
307
 
 
308
                                pdstBase = ilbmScanlineNoBankSwitch(pdstBase, x, y, auxDst);
 
309
                                xpos = x;
 
310
                                xchar = xpos & PIM;
 
311
 
 
312
                                for (i = 0; i < nglyph; i++) {
 
313
                                        pci = ppci[i];
 
314
 
 
315
                                        ppos[i].xpos = xpos;
 
316
                                        ppos[i].xchar = xchar;
 
317
                                        ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing;
 
318
                                        ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing;
 
319
                                        ppos[i].topEdge = y - pci->metrics.ascent;
 
320
                                        ppos[i].bottomEdge = y + pci->metrics.descent;
 
321
                                        ppos[i].pdstBase = pdstBase;
 
322
                                        ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
 
323
 
 
324
                                        xpos += pci->metrics.characterWidth;
 
325
                                        xchar += pci->metrics.characterWidth;
 
326
                                        if (xchar > PLST) {
 
327
                                                xchar &= PIM;
 
328
                                                pdstBase++;
 
329
                                        } else if (xchar < 0) {
 
330
                                                xchar += PPW;
 
331
                                                pdstBase--;
 
332
                                        }
 
333
                                }
 
334
 
 
335
                                cclip = pGC->pCompositeClip;
 
336
                                pbox = REGION_RECTS(cclip);
 
337
                                nbox = REGION_NUM_RECTS(cclip);
 
338
 
 
339
                                /* HACK ALERT
 
340
                                   since we continue out of the loop below so often, it
 
341
                                   is easier to increment pbox at the  top than at the end.
 
342
                                   don't try this at home.
 
343
                                */
 
344
                                pbox--;
 
345
                                while (nbox--) {
 
346
                                        pbox++;
 
347
                                        clip.x1 = max(bbox.x1, pbox->x1);
 
348
                                        clip.y1 = max(bbox.y1, pbox->y1);
 
349
                                        clip.x2 = min(bbox.x2, pbox->x2);
 
350
                                        clip.y2 = min(bbox.y2, pbox->y2);
 
351
                                        if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1))
 
352
                                                continue;
 
353
 
 
354
                                        for (i = 0; i < nglyph; i++) {
 
355
                                                pci = ppci[i];
 
356
                                                xchar = ppos[i].xchar;
 
357
 
 
358
                                                /* clip the left and right edges */
 
359
                                                if (ppos[i].leftEdge < clip.x1)
 
360
                                                        leftEdge = clip.x1;
 
361
                                                else
 
362
                                                        leftEdge = ppos[i].leftEdge;
 
363
 
 
364
                                                if (ppos[i].rightEdge > clip.x2)
 
365
                                                        rightEdge = clip.x2;
 
366
                                                else
 
367
                                                        rightEdge = ppos[i].rightEdge;
 
368
 
 
369
                                                w = rightEdge - leftEdge;
 
370
                                                if (w <= 0)
 
371
                                                        continue;
 
372
 
 
373
                                                /* clip the top and bottom edges */
 
374
                                                if (ppos[i].topEdge < clip.y1)
 
375
                                                        topEdge = clip.y1;
 
376
                                                else
 
377
                                                        topEdge = ppos[i].topEdge;
 
378
 
 
379
                                                if (ppos[i].bottomEdge > clip.y2)
 
380
                                                        bottomEdge = clip.y2;
 
381
                                                else
 
382
                                                        bottomEdge = ppos[i].bottomEdge;
 
383
 
 
384
                                                hSave = bottomEdge - topEdge;
 
385
                                                if (hSave <= 0)
 
386
                                                        continue;
 
387
 
 
388
                                                glyphRow = (topEdge - y) + pci->metrics.ascent;
 
389
                                                widthGlyph = ppos[i].widthGlyph;
 
390
                                                pglyphSave = FONTGLYPHBITS(pglyphBase, pci);
 
391
                                                pglyphSave += (glyphRow * widthGlyph);
 
392
 
 
393
                                                glyphCol = (leftEdge - ppos[i].xpos) -
 
394
                                                                   (pci->metrics.leftSideBearing);
 
395
                                                getWidth = w + glyphCol;
 
396
 
 
397
                                                pdstSave = ilbmScanlineDelta(ppos[i].pdstBase, -(y-topEdge),
 
398
                                                                                                                          auxDst);
 
399
                                                xoff = xchar + (leftEdge - ppos[i].xpos);
 
400
                                                if (xoff > PLST) {
 
401
                                                        xoff &= PIM;
 
402
                                                        pdstSave++;
 
403
                                                } else if (xoff < 0) {
 
404
                                                        xoff += PPW;
 
405
                                                        pdstSave--;
 
406
                                                }
 
407
 
 
408
                                                for (d = 0; d < depthDst; d++) {
 
409
                                                        h = hSave;
 
410
                                                        pdst = pdstSave;
 
411
                                                        pdstSave += widthDst;   /* @@@ NEXT PLANE @@@ */
 
412
                                                        pglyph = pglyphSave;
 
413
 
 
414
                                                        if ((xoff + w) <= PPW) {
 
415
                                                                maskpartialbits(xoff, w, startmask);
 
416
 
 
417
                                                                switch (rrops[d]) {
 
418
                                                                        case RROP_BLACK:
 
419
                                                                                while (h--) {
 
420
                                                                                        getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
 
421
                                                                                        *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask);
 
422
                                                                                        pglyph += widthGlyph;
 
423
                                                                                        ilbmScanlineInc(pdst, auxDst);
 
424
                                                                                }
 
425
                                                                                break;
 
426
                                                                        case RROP_WHITE:
 
427
                                                                                while (h--) {
 
428
                                                                                        getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
 
429
                                                                                        *pdst |= SCRRIGHT(tmpSrc, xoff) & startmask;
 
430
                                                                                        pglyph += widthGlyph;
 
431
                                                                                        ilbmScanlineInc(pdst, auxDst);
 
432
                                                                                }
 
433
                                                                                break;
 
434
                                                                        case RROP_NOP:
 
435
                                                                                break;
 
436
                                                                }
 
437
                                                        } else {
 
438
                                                                maskPPWbits(xoff, w, startmask, endmask);
 
439
                                                                nFirst = PPW - xoff;
 
440
 
 
441
                                                                switch (rrops[d]) {
 
442
                                                                        case RROP_BLACK:
 
443
                                                                                while (h--) {
 
444
                                                                                        getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
 
445
                                                                                        *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask);
 
446
                                                                                        *(pdst+1) &= ~(SCRLEFT(tmpSrc, nFirst) & endmask);
 
447
                                                                                        pglyph += widthGlyph;
 
448
                                                                                        ilbmScanlineInc(pdst, auxDst);
 
449
                                                                                }
 
450
                                                                                break;
 
451
                                                                        case RROP_WHITE:
 
452
                                                                                while (h--) {
 
453
                                                                                        getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc);
 
454
                                                                                        *pdst |= SCRRIGHT(tmpSrc, xoff) & startmask;
 
455
                                                                                        *(pdst+1) |= SCRLEFT(tmpSrc, nFirst) & endmask;
 
456
                                                                                        pglyph += widthGlyph;
 
457
                                                                                        ilbmScanlineInc(pdst, auxDst);
 
458
                                                                                }
 
459
                                                                                break;
 
460
                                                                        case RROP_NOP:
 
461
                                                                                break;
 
462
                                                                }
 
463
                                                        }
 
464
                                                } /* depth */
 
465
                                        } /* for each glyph */
 
466
                                } /* while nbox-- */
 
467
                                DEALLOCATE_LOCAL(ppos);
 
468
                                break;
 
469
                        }
 
470
 
 
471
                default:
 
472
                        break;
 
473
        }
 
474
}