1 /***********************************************************
3 Copyright (c) 1987 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 ******************************************************************/
49 #ifdef HAVE_DIX_CONFIG_H
50 #include <dix-config.h>
57 #include <X11/Xproto.h>
59 #include "dixfontstr.h"
60 #include <X11/fonts/fontstruct.h>
62 #include "windowstr.h"
63 #include "pixmapstr.h"
64 #include "scrnintstr.h"
72 static void afbDestroyGC(GCPtr
);
73 static void afbValidateGC(GCPtr
, unsigned long, DrawablePtr
);
75 static GCFuncs afbFuncs
= {
85 static GCOps afbGCOps
= {
109 afbReduceOpaqueStipple(PixelType fg
, PixelType bg
, unsigned long planemask
,
110 int depth
, unsigned char *rop
)
113 register Pixel mask
= 1;
117 for (d
= 0; d
< depth
; d
++, mask
<<= 1) {
118 if (!(planemask
& mask
))
120 else if (!(bg
& mask
)) {
121 /* Both fg and bg have a 0 or 1 in this plane */
127 /* Both fg and bg have different bits on this plane */
131 rop
[d
] = RROP_INVERT
;
142 pGC
->clientClip
= NULL
;
143 pGC
->clientClipType
= CT_NONE
;
145 /* some of the output primitives aren't really necessary, since
146 they will be filled in ValidateGC because of dix/CreateGC()
147 setting all the change bits. Others are necessary because although
148 they depend on being a monochrome frame buffer, they don't change
151 pGC
->ops
= &afbGCOps
;
152 pGC
->funcs
= &afbFuncs
;
154 /* afb wants to translate before scan convesion */
155 pGC
->miTranslate
= 1;
157 pPriv
= (afbPrivGC
*)(pGC
->devPrivates
[afbGCPrivateIndex
].ptr
);
158 afbReduceRop(pGC
->alu
, pGC
->fgPixel
, pGC
->planemask
, pGC
->depth
,
160 afbReduceOpaqueStipple(pGC
->fgPixel
, pGC
->bgPixel
, pGC
->planemask
,
161 pGC
->depth
, pPriv
->rropOS
);
164 pGC
->pRotatedPixmap
= NullPixmap
;
165 pGC
->freeCompClip
= FALSE
;
170 afbComputeCompositeClip(GCPtr pGC
, DrawablePtr pDrawable
)
172 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
173 WindowPtr pWin
= (WindowPtr
) pDrawable
;
175 Bool freeTmpClip
, freeCompClip
;
177 if (pGC
->subWindowMode
== IncludeInferiors
) {
178 pregWin
= NotClippedByChildren(pWin
);
181 pregWin
= &pWin
->clipList
;
184 freeCompClip
= pGC
->freeCompClip
;
187 * if there is no client clip, we can get by with just keeping the
188 * pointer we got, and remembering whether or not should destroy (or
189 * maybe re-use) it later. this way, we avoid unnecessary copying of
190 * regions. (this wins especially if many clients clip by children
191 * and have no client clip.)
193 if (pGC
->clientClipType
== CT_NONE
) {
195 REGION_DESTROY(pGC
->pScreen
, pGC
->pCompositeClip
);
196 pGC
->pCompositeClip
= pregWin
;
197 pGC
->freeCompClip
= freeTmpClip
;
200 * we need one 'real' region to put into the composite clip. if
201 * pregWin the current composite clip are real, we can get rid of
202 * one. if pregWin is real and the current composite clip isn't,
203 * use pregWin for the composite clip. if the current composite
204 * clip is real and pregWin isn't, use the current composite
205 * clip. if neither is real, create a new region.
208 REGION_TRANSLATE(pGC
->pScreen
, pGC
->clientClip
,
209 pDrawable
->x
+ pGC
->clipOrg
.x
,
210 pDrawable
->y
+ pGC
->clipOrg
.y
);
213 REGION_INTERSECT(pGC
->pScreen
, pGC
->pCompositeClip
, pregWin
,
216 REGION_DESTROY(pGC
->pScreen
, pregWin
);
217 } else if (freeTmpClip
) {
218 REGION_INTERSECT(pGC
->pScreen
, pregWin
, pregWin
, pGC
->clientClip
);
219 pGC
->pCompositeClip
= pregWin
;
221 pGC
->pCompositeClip
= REGION_CREATE(pGC
->pScreen
, NullBox
, 0);
222 REGION_INTERSECT(pGC
->pScreen
, pGC
->pCompositeClip
,
223 pregWin
, pGC
->clientClip
);
225 pGC
->freeCompClip
= TRUE
;
226 REGION_TRANSLATE(pGC
->pScreen
, pGC
->clientClip
,
227 -(pDrawable
->x
+ pGC
->clipOrg
.x
),
228 -(pDrawable
->y
+ pGC
->clipOrg
.y
));
230 } /* end of composite clip for a window */
234 /* XXX should we translate by drawable.x/y here ? */
237 pixbounds
.x2
= pDrawable
->width
;
238 pixbounds
.y2
= pDrawable
->height
;
240 if (pGC
->freeCompClip
) {
241 REGION_RESET(pGC
->pScreen
, pGC
->pCompositeClip
, &pixbounds
);
243 pGC
->freeCompClip
= TRUE
;
244 pGC
->pCompositeClip
= REGION_CREATE(pGC
->pScreen
, &pixbounds
, 1);
247 if (pGC
->clientClipType
== CT_REGION
) {
248 REGION_TRANSLATE(pGC
->pScreen
, pGC
->pCompositeClip
, -pGC
->clipOrg
.x
,
250 REGION_INTERSECT(pGC
->pScreen
, pGC
->pCompositeClip
,
251 pGC
->pCompositeClip
, pGC
->clientClip
);
252 REGION_TRANSLATE(pGC
->pScreen
, pGC
->pCompositeClip
, pGC
->clipOrg
.x
,
255 } /* end of composite clip for pixmap */
256 } /* end afbComputeCompositeClip */
258 /* Clipping conventions
259 if the drawable is a window
260 CT_REGION ==> pCompositeClip really is the composite
261 CT_other ==> pCompositeClip is the window clip region
262 if the drawable is a pixmap
263 CT_REGION ==> pCompositeClip is the translated client region
264 clipped to the pixmap boundary
265 CT_other ==> pCompositeClip is the pixmap bounding box
270 afbValidateGC(pGC
, changes
, pDrawable
)
272 unsigned long changes
;
273 DrawablePtr pDrawable
;
275 register afbPrivGCPtr devPriv
;
276 int mask
; /* stateChanges */
277 int index
; /* used for stepping through bitfields */
278 int xrot
, yrot
; /* rotations for tile and stipple pattern */
279 /* flags for changing the proc vector
280 and updating things in devPriv
282 int new_rotate
, new_rrop
, new_line
, new_text
, new_fill
;
283 DDXPointRec oldOrg
; /* origin of thing GC was last used with */
285 oldOrg
= pGC
->lastWinOrg
;
287 pGC
->lastWinOrg
.x
= pDrawable
->x
;
288 pGC
->lastWinOrg
.y
= pDrawable
->y
;
290 /* we need to re-rotate the tile if the previous window/pixmap
291 origin (oldOrg) differs from the new window/pixmap origin
294 new_rotate
= (oldOrg
.x
!= pGC
->lastWinOrg
.x
) ||
295 (oldOrg
.y
!= pGC
->lastWinOrg
.y
);
298 devPriv
= ((afbPrivGCPtr
)(pGC
->devPrivates
[afbGCPrivateIndex
].ptr
));
302 if the client clip is different or moved OR
303 the subwindowMode has changed OR
304 the window's clip has changed since the last validation
305 we need to recompute the composite clip
307 if ((changes
& (GCClipXOrigin
|GCClipYOrigin
|GCClipMask
|GCSubwindowMode
)) ||
308 (pDrawable
->serialNumber
!= (pGC
->serialNumber
& DRAWABLE_SERIAL_BITS
)))
309 afbComputeCompositeClip(pGC
, pDrawable
);
318 index
= lowbit(mask
);
321 /* this switch acculmulates a list of which procedures
322 might have to change due to changes in the GC. in
323 some cases (e.g. changing one 16 bit tile for another)
324 we might not really need a change, but the code is
326 this sort of batching wins if, for example, the alu
327 and the font have been changed, or any other pair
328 of items that both change the same thing.
337 new_rrop
= TRUE
; /* for opaque stipples */
359 if(pGC
->stipple
== (PixmapPtr
)NULL
)
365 case GCTileStipXOrigin
:
369 case GCTileStipYOrigin
:
376 case GCSubwindowMode
:
378 case GCGraphicsExposures
:
397 /* deal with the changes we've collected .
398 new_rrop must be done first because subsequent things
402 if(new_rotate
|| new_fill
) {
403 Bool new_pix
= FALSE
;
405 /* figure out how much to rotate */
406 xrot
= pGC
->patOrg
.x
;
407 yrot
= pGC
->patOrg
.y
;
408 xrot
+= pDrawable
->x
;
409 yrot
+= pDrawable
->y
;
411 switch (pGC
->fillStyle
) {
413 /* copy current tile and stipple */
414 if (!pGC
->tileIsPixel
&&
415 (pGC
->tile
.pixmap
->drawable
.width
<= PPW
) &&
416 !(pGC
->tile
.pixmap
->drawable
.width
&
417 (pGC
->tile
.pixmap
->drawable
.width
- 1))) {
418 afbCopyRotatePixmap(pGC
->tile
.pixmap
, &pGC
->pRotatedPixmap
,
424 case FillOpaqueStippled
:
425 if (pGC
->stipple
&& (pGC
->stipple
->drawable
.width
<= PPW
) &&
426 !(pGC
->stipple
->drawable
.width
&
427 (pGC
->stipple
->drawable
.width
- 1))) {
428 afbCopyRotatePixmap(pGC
->stipple
, &pGC
->pRotatedPixmap
,
433 /* destroy any previously rotated tile or stipple */
434 if (!new_pix
&& pGC
->pRotatedPixmap
) {
435 (*pDrawable
->pScreen
->DestroyPixmap
)(pGC
->pRotatedPixmap
);
436 pGC
->pRotatedPixmap
= (PixmapPtr
)NULL
;
441 * duck out here when the GC is unchanged
447 if (new_rrop
|| new_fill
) {
448 afbReduceRop(pGC
->alu
, pGC
->fgPixel
, pGC
->planemask
, pDrawable
->depth
,
450 afbReduceOpaqueStipple(pGC
->fgPixel
, pGC
->bgPixel
, pGC
->planemask
,
451 pGC
->depth
, devPriv
->rropOS
);
455 if (new_line
|| new_fill
|| new_text
) {
456 if (!pGC
->ops
->devPrivate
.val
) {
457 pGC
->ops
= miCreateGCOps(pGC
->ops
);
458 pGC
->ops
->devPrivate
.val
= 1;
462 if (new_line
|| new_fill
) {
463 if (pGC
->lineWidth
== 0) {
464 if (pGC
->lineStyle
== LineSolid
&& pGC
->fillStyle
== FillSolid
)
465 pGC
->ops
->PolyArc
= afbZeroPolyArcSS
;
467 pGC
->ops
->PolyArc
= miZeroPolyArc
;
469 pGC
->ops
->PolyArc
= miPolyArc
;
470 if (pGC
->lineStyle
== LineSolid
) {
471 if(pGC
->lineWidth
== 0) {
472 if (pGC
->fillStyle
== FillSolid
) {
473 pGC
->ops
->PolySegment
= afbSegmentSS
;
474 pGC
->ops
->Polylines
= afbLineSS
;
478 pGC
->ops
->PolySegment
= miPolySegment
;
479 pGC
->ops
->Polylines
= miZeroLine
;
482 pGC
->ops
->PolySegment
= miPolySegment
;
483 pGC
->ops
->Polylines
= miWideLine
;
486 if(pGC
->lineWidth
== 0 && pGC
->fillStyle
== FillSolid
) {
487 pGC
->ops
->PolySegment
= afbSegmentSD
;
488 pGC
->ops
->Polylines
= afbLineSD
;
490 pGC
->ops
->PolySegment
= miPolySegment
;
491 pGC
->ops
->Polylines
= miWideDash
;
496 if (new_text
|| new_fill
) {
498 (FONTMAXBOUNDS(pGC
->font
,rightSideBearing
) -
499 FONTMINBOUNDS(pGC
->font
,leftSideBearing
) > 32 ||
500 FONTMINBOUNDS(pGC
->font
,characterWidth
) < 0)) {
501 pGC
->ops
->PolyGlyphBlt
= miPolyGlyphBlt
;
502 pGC
->ops
->ImageGlyphBlt
= miImageGlyphBlt
;
504 /* special case ImageGlyphBlt for terminal emulator fonts */
506 TERMINALFONT(pGC
->font
)) {
507 pGC
->ops
->ImageGlyphBlt
= afbTEGlyphBlt
;
509 pGC
->ops
->ImageGlyphBlt
= afbImageGlyphBlt
;
512 /* now do PolyGlyphBlt */
513 if (pGC
->fillStyle
== FillSolid
) {
514 pGC
->ops
->PolyGlyphBlt
= afbPolyGlyphBlt
;
516 pGC
->ops
->PolyGlyphBlt
= miPolyGlyphBlt
;
522 /* install a suitable fillspans and pushpixels */
523 pGC
->ops
->PushPixels
= afbPushPixels
;
524 pGC
->ops
->FillPolygon
= miFillPolygon
;
525 pGC
->ops
->PolyFillArc
= miPolyFillArc
;
527 switch (pGC
->fillStyle
) {
529 pGC
->ops
->FillSpans
= afbSolidFS
;
530 pGC
->ops
->FillPolygon
= afbFillPolygonSolid
;
531 pGC
->ops
->PolyFillArc
= afbPolyFillArcSolid
;
534 if (pGC
->pRotatedPixmap
)
535 pGC
->ops
->FillSpans
= afbTileFS
;
537 pGC
->ops
->FillSpans
= afbUnnaturalTileFS
;
539 case FillOpaqueStippled
:
540 if (pGC
->pRotatedPixmap
)
541 pGC
->ops
->FillSpans
= afbOpaqueStippleFS
;
543 pGC
->ops
->FillSpans
= afbUnnaturalOpaqueStippleFS
;
547 if (pGC
->pRotatedPixmap
)
548 pGC
->ops
->FillSpans
= afbStippleFS
;
550 pGC
->ops
->FillSpans
= afbUnnaturalStippleFS
;
553 } /* end of new_fill */
560 if (pGC
->pRotatedPixmap
)
561 (*pGC
->pScreen
->DestroyPixmap
)(pGC
->pRotatedPixmap
);
562 if (pGC
->freeCompClip
)
563 REGION_DESTROY(pGC
->pScreen
, pGC
->pCompositeClip
);
564 miDestroyGCOps(pGC
->ops
);
568 afbReduceRop(alu
, src
, planemask
, depth
, rop
)
571 register unsigned long planemask
;
573 register unsigned char *rop
;
576 register Pixel mask
= 1;
578 for (d
= 0; d
< depth
; d
++, mask
<<= 1) {
579 if (!(planemask
& mask
))
581 else if ((src
& mask
) == 0) /* src is black */
608 rop
[d
] = RROP_INVERT
;
611 rop
[d
] = RROP_INVERT
;
614 rop
[d
] = RROP_INVERT
;
617 rop
[d
] = RROP_INVERT
;
632 else /* src is white */
641 rop
[d
] = RROP_INVERT
;
653 rop
[d
] = RROP_INVERT
;
665 rop
[d
] = RROP_INVERT
;
677 rop
[d
] = RROP_INVERT
;