1
/* $XFree86: xc/programs/Xserver/ilbm/ilbmgc.c,v 3.0 1996/08/18 01:53:52 dawes Exp $ */
2
/***********************************************************
4
Copyright (c) 1987 X Consortium
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of the X Consortium shall not be
24
used in advertising or otherwise to promote the sale, use or other dealings
25
in this Software without prior written authorization from the X Consortium.
28
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
32
Permission to use, copy, modify, and distribute this software and its
33
documentation for any purpose and without fee is hereby granted,
34
provided that the above copyright notice appear in all copies and that
35
both that copyright notice and this permission notice appear in
36
supporting documentation, and that the name of Digital not be
37
used in advertising or publicity pertaining to distribution of the
38
software without specific, written prior permission.
40
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
48
******************************************************************/
49
/* $XConsortium: ilbmgc.c,v 5.35 94/04/17 20:28:23 dpw Exp $ */
51
/* Modified jun 95 by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
52
to use interleaved bitplanes instead of normal bitplanes */
54
#ifdef HAVE_DIX_CONFIG_H
55
#include <dix-config.h>
60
#include <X11/Xproto.h>
62
#include "dixfontstr.h"
63
#include <X11/fonts/fontstruct.h>
65
#include "windowstr.h"
66
#include "pixmapstr.h"
67
#include "scrnintstr.h"
75
static GCFuncs ilbmFuncs = {
85
static GCOps ilbmGCOps = {
106
#ifdef NEED_LINEHELPER
118
pGC->clientClip = NULL;
119
pGC->clientClipType = CT_NONE;
121
/* some of the output primitives aren't really necessary, since
122
they will be filled in ValidateGC because of dix/CreateGC()
123
setting all the change bits. Others are necessary because although
124
they depend on being a monochrome frame buffer, they don't change
127
pGC->ops = &ilbmGCOps;
128
pGC->funcs = &ilbmFuncs;
130
/* ilbm wants to translate before scan convesion */
131
pGC->miTranslate = 1;
133
pPriv = (ilbmPrivGC *)(pGC->devPrivates[ilbmGCPrivateIndex].ptr);
134
ilbmReduceRop(pGC->alu, pGC->fgPixel, pGC->planemask, pGC->depth,
136
ilbmReduceOpaqueStipple(pGC->fgPixel, pGC->bgPixel, pGC->planemask,
137
pGC->depth, pPriv->rropOS);
140
pGC->pRotatedPixmap = NullPixmap;
141
pGC->freeCompClip = FALSE;
145
/* Clipping conventions
146
if the drawable is a window
147
CT_REGION ==> pCompositeClip really is the composite
148
CT_other ==> pCompositeClip is the window clip region
149
if the drawable is a pixmap
150
CT_REGION ==> pCompositeClip is the translated client region
151
clipped to the pixmap boundary
152
CT_other ==> pCompositeClip is the pixmap bounding box
157
ilbmValidateGC(pGC, changes, pDrawable)
159
unsigned long changes;
160
DrawablePtr pDrawable;
162
register ilbmPrivGCPtr devPriv;
163
int mask; /* stateChanges */
164
int index; /* used for stepping through bitfields */
165
int xrot, yrot; /* rotations for tile and stipple pattern */
166
int rrop; /* reduced rasterop */
167
/* flags for changing the proc vector
168
and updating things in devPriv
170
int new_rotate, new_rrop, new_line, new_text, new_fill;
171
DDXPointRec oldOrg; /* origin of thing GC was last used with */
173
oldOrg = pGC->lastWinOrg;
175
pGC->lastWinOrg.x = pDrawable->x;
176
pGC->lastWinOrg.y = pDrawable->y;
178
/* we need to re-rotate the tile if the previous window/pixmap
179
origin (oldOrg) differs from the new window/pixmap origin
182
new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
183
(oldOrg.y != pGC->lastWinOrg.y);
186
devPriv = ((ilbmPrivGCPtr)(pGC->devPrivates[ilbmGCPrivateIndex].ptr));
190
if the client clip is different or moved OR
191
the subwindowMode has changed OR
192
the window's clip has changed since the last validation
193
we need to recompute the composite clip
195
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
196
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
197
ilbmComputeCompositeClip(pGC, pDrawable);
206
index = lowbit(mask);
209
/* this switch acculmulates a list of which procedures
210
might have to change due to changes in the GC. in
211
some cases (e.g. changing one 16 bit tile for another)
212
we might not really need a change, but the code is
214
this sort of batching wins if, for example, the alu
215
and the font have been changed, or any other pair
216
of items that both change the same thing.
225
new_rrop = TRUE; /* for opaque stipples */
240
if (pGC->tileIsPixel)
247
if (pGC->stipple == (PixmapPtr)NULL)
253
case GCTileStipXOrigin:
257
case GCTileStipYOrigin:
264
case GCSubwindowMode:
266
case GCGraphicsExposures:
285
/* deal with the changes we've collected .
286
new_rrop must be done first because subsequent things
290
if (new_rotate || new_fill) {
291
Bool new_pix = FALSE;
293
/* figure out how much to rotate */
294
xrot = pGC->patOrg.x;
295
yrot = pGC->patOrg.y;
296
xrot += pDrawable->x;
297
yrot += pDrawable->y;
299
switch (pGC->fillStyle) {
301
/* copy current tile and stipple */
302
if (!pGC->tileIsPixel &&
303
(pGC->tile.pixmap->drawable.width <= PPW) &&
304
!(pGC->tile.pixmap->drawable.width &
305
(pGC->tile.pixmap->drawable.width - 1))) {
306
ilbmCopyRotatePixmap(pGC->tile.pixmap, &pGC->pRotatedPixmap,
312
case FillOpaqueStippled:
313
if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) &&
314
!(pGC->stipple->drawable.width &
315
(pGC->stipple->drawable.width - 1))) {
316
ilbmCopyRotatePixmap(pGC->stipple, &pGC->pRotatedPixmap,
321
/* destroy any previously rotated tile or stipple */
322
if (!new_pix && pGC->pRotatedPixmap) {
323
(*pDrawable->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
324
pGC->pRotatedPixmap = (PixmapPtr)NULL;
329
* duck out here when the GC is unchanged
335
if (new_rrop || new_fill) {
336
ilbmReduceRop(pGC->alu, pGC->fgPixel, pGC->planemask, pDrawable->depth,
338
ilbmReduceOpaqueStipple(pGC->fgPixel, pGC->bgPixel, pGC->planemask,
339
pGC->depth, devPriv->rropOS);
343
if (new_line || new_fill || new_text) {
344
if (!pGC->ops->devPrivate.val) {
345
pGC->ops = miCreateGCOps(pGC->ops);
346
pGC->ops->devPrivate.val = 1;
350
if (new_line || new_fill) {
351
if (pGC->lineWidth == 0) {
352
if (pGC->lineStyle == LineSolid && pGC->fillStyle == FillSolid)
353
pGC->ops->PolyArc = ilbmZeroPolyArcSS;
355
pGC->ops->PolyArc = miZeroPolyArc;
357
pGC->ops->PolyArc = miPolyArc;
358
if (pGC->lineStyle == LineSolid) {
359
if (pGC->lineWidth == 0) {
360
if (pGC->fillStyle == FillSolid) {
361
pGC->ops->PolySegment = ilbmSegmentSS;
362
pGC->ops->Polylines = ilbmLineSS;
364
pGC->ops->PolySegment = miPolySegment;
365
pGC->ops->Polylines = miZeroLine;
368
pGC->ops->PolySegment = miPolySegment;
369
pGC->ops->Polylines = miWideLine;
372
if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
373
pGC->ops->PolySegment = ilbmSegmentSD;
374
pGC->ops->Polylines = ilbmLineSD;
376
pGC->ops->PolySegment = miPolySegment;
377
pGC->ops->Polylines = miWideDash;
382
if (new_text || new_fill) {
384
(FONTMAXBOUNDS(pGC->font,rightSideBearing) -
385
FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
386
FONTMINBOUNDS(pGC->font,characterWidth) < 0)) {
387
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
388
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
390
/* special case ImageGlyphBlt for terminal emulator fonts */
392
TERMINALFONT(pGC->font)) {
393
pGC->ops->ImageGlyphBlt = ilbmTEGlyphBlt;
395
pGC->ops->ImageGlyphBlt = ilbmImageGlyphBlt;
398
/* now do PolyGlyphBlt */
399
if (pGC->fillStyle == FillSolid) {
400
pGC->ops->PolyGlyphBlt = ilbmPolyGlyphBlt;
402
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
408
/* install a suitable fillspans and pushpixels */
409
pGC->ops->PushPixels = ilbmPushPixels;
410
pGC->ops->FillPolygon = miFillPolygon;
411
pGC->ops->PolyFillArc = miPolyFillArc;
413
switch (pGC->fillStyle) {
415
pGC->ops->FillSpans = ilbmSolidFS;
416
pGC->ops->FillPolygon = ilbmFillPolygonSolid;
417
pGC->ops->PolyFillArc = ilbmPolyFillArcSolid;
420
if (pGC->pRotatedPixmap)
421
pGC->ops->FillSpans = ilbmTileFS;
423
pGC->ops->FillSpans = ilbmUnnaturalTileFS;
425
case FillOpaqueStippled:
426
if (pGC->pRotatedPixmap)
427
pGC->ops->FillSpans = ilbmOpaqueStippleFS;
429
pGC->ops->FillSpans = ilbmUnnaturalOpaqueStippleFS;
433
if (pGC->pRotatedPixmap)
434
pGC->ops->FillSpans = ilbmStippleFS;
436
pGC->ops->FillSpans = ilbmUnnaturalStippleFS;
439
} /* end of new_fill */
446
if (pGC->pRotatedPixmap)
447
(*pGC->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
448
if (pGC->freeCompClip)
449
REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip);
450
miDestroyGCOps(pGC->ops);
453
/* table to map alu(src, dst) to alu(~src, dst) */
454
int ilbmInverseAlu[16] = {
474
ilbmReduceOpaqueStipple(fg, bg, planemask, depth, rop)
475
register PixelType fg;
476
register PixelType bg;
477
register unsigned long planemask;
479
register unsigned char *rop;
482
register Pixel mask = 1;
486
for (d = 0; d < depth; d++, mask <<= 1) {
487
if (!(planemask & mask))
489
else if (!(bg & mask)) {
490
/* Both fg and bg have a 0 or 1 in this plane */
496
/* Both fg and bg have different bits on this plane */
500
rop[d] = RROP_INVERT;
506
ilbmReduceRop(alu, src, planemask, depth, rop)
509
register unsigned long planemask;
511
register unsigned char *rop;
514
register Pixel mask = 1;
516
for (d = 0; d < depth; d++, mask <<= 1) {
517
if (!(planemask & mask))
519
else if ((src & mask) == 0) /* src is black */
546
rop[d] = RROP_INVERT;
549
rop[d] = RROP_INVERT;
552
rop[d] = RROP_INVERT;
555
rop[d] = RROP_INVERT;
570
else /* src is white */
579
rop[d] = RROP_INVERT;
591
rop[d] = RROP_INVERT;
603
rop[d] = RROP_INVERT;
615
rop[d] = RROP_INVERT;
625
ilbmComputeCompositeClip(pGC, pDrawable)
627
DrawablePtr pDrawable;
629
ScreenPtr pScreen = pGC->pScreen;
631
if (pDrawable->type == DRAWABLE_WINDOW) {
632
WindowPtr pWin = (WindowPtr) pDrawable;
634
Bool freeTmpClip, freeCompClip;
636
if (pGC->subWindowMode == IncludeInferiors) {
637
pregWin = NotClippedByChildren(pWin);
640
pregWin = &pWin->clipList;
643
freeCompClip = pGC->freeCompClip;
646
* if there is no client clip, we can get by with just keeping the
647
* pointer we got, and remembering whether or not should destroy (or
648
* maybe re-use) it later. this way, we avoid unnecessary copying of
649
* regions. (this wins especially if many clients clip by children
650
* and have no client clip.)
652
if (pGC->clientClipType == CT_NONE) {
654
REGION_DESTROY(pScreen, pGC->pCompositeClip);
655
pGC->pCompositeClip = pregWin;
656
pGC->freeCompClip = freeTmpClip;
659
* we need one 'real' region to put into the composite clip. if
660
* pregWin the current composite clip are real, we can get rid of
661
* one. if pregWin is real and the current composite clip isn't,
662
* use pregWin for the composite clip. if the current composite
663
* clip is real and pregWin isn't, use the current composite
664
* clip. if neither is real, create a new region.
667
REGION_TRANSLATE(pScreen, pGC->clientClip,
668
pDrawable->x + pGC->clipOrg.x,
669
pDrawable->y + pGC->clipOrg.y);
672
REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip, pregWin,
675
REGION_DESTROY(pScreen, pregWin);
676
} else if (freeTmpClip) {
677
REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
678
pGC->pCompositeClip = pregWin;
680
pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
681
REGION_INTERSECT(pScreen, pGC->pCompositeClip,
682
pregWin, pGC->clientClip);
684
pGC->freeCompClip = TRUE;
685
REGION_TRANSLATE(pScreen, pGC->clientClip,
686
-(pDrawable->x + pGC->clipOrg.x),
687
-(pDrawable->y + pGC->clipOrg.y));
689
} /* end of composite clip for a window */
693
/* XXX should we translate by drawable.x/y here ? */
696
pixbounds.x2 = pDrawable->width;
697
pixbounds.y2 = pDrawable->height;
699
if (pGC->freeCompClip) {
700
REGION_RESET(pScreen, pGC->pCompositeClip, &pixbounds);
702
pGC->freeCompClip = TRUE;
703
pGC->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
706
if (pGC->clientClipType == CT_REGION) {
707
REGION_TRANSLATE(pScreen, pGC->pCompositeClip, -pGC->clipOrg.x,
709
REGION_INTERSECT(pScreen, pGC->pCompositeClip,
710
pGC->pCompositeClip, pGC->clientClip);
711
REGION_TRANSLATE(pScreen, pGC->pCompositeClip, pGC->clipOrg.x,
714
} /* end of composite clip for pixmap */
715
} /* end ilbmComputeCompositeClip */