1/***********************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46******************************************************************/
47
48
49#ifdef HAVE_DIX_CONFIG_H
50#include <dix-config.h>
51#endif
52
53#include	<X11/X.h>
54#include	<X11/Xmd.h>
55#include	<X11/Xproto.h>
56#include	"misc.h"
57#include	<X11/fonts/fontstruct.h>
58#include	"dixfontstr.h"
59#include	"gcstruct.h"
60#include	"windowstr.h"
61#include	"scrnintstr.h"
62#include	"pixmap.h"
63#include	"servermd.h"
64#include        "mi.h"
65
66/*
67    machine-independent glyph blt.
68    assumes that glyph bits in snf are written in bytes,
69have same bit order as the server's bitmap format,
70and are byte padded.  this corresponds to the snf distributed
71with the sample server.
72
73    get a scratch GC.
74    in the scratch GC set alu = GXcopy, fg = 1, bg = 0
75    allocate a bitmap big enough to hold the largest glyph in the font
76    validate the scratch gc with the bitmap
77    for each glyph
78	carefully put the bits of the glyph in a buffer,
79	    padded to the server pixmap scanline padding rules
80	fake a call to PutImage from the buffer into the bitmap
81	use the bitmap in a call to PushPixels
82*/
83
84void
85miPolyGlyphBlt(
86    DrawablePtr pDrawable,
87    GC		*pGC,
88    int		x,
89    int		y,
90    unsigned int nglyph,
91    CharInfoPtr *ppci,		/* array of character info */
92    pointer      pglyphBase	/* start of array of glyphs */
93    )
94{
95    int width, height;
96    PixmapPtr pPixmap;
97    int nbyLine;		/* bytes per line of padded pixmap */
98    FontPtr pfont;
99    GCPtr pGCtmp;
100    int i;
101    int j;
102    unsigned char *pbits;	/* buffer for PutImage */
103    unsigned char *pb;		/* temp pointer into buffer */
104    CharInfoPtr pci;		/* currect char info */
105    unsigned char *pglyph;	/* pointer bits in glyph */
106    int gWidth, gHeight;	/* width and height of glyph */
107    int nbyGlyphWidth;		/* bytes per scanline of glyph */
108    int nbyPadGlyph;		/* server padded line of glyph */
109
110    ChangeGCVal gcvals[3];
111
112    if (pGC->miTranslate)
113    {
114	x += pDrawable->x;
115	y += pDrawable->y;
116    }
117
118    pfont = pGC->font;
119    width = FONTMAXBOUNDS(pfont,rightSideBearing) -
120	    FONTMINBOUNDS(pfont,leftSideBearing);
121    height = FONTMAXBOUNDS(pfont,ascent) +
122	     FONTMAXBOUNDS(pfont,descent);
123
124    pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen,
125						  width, height, 1,
126						  CREATE_PIXMAP_USAGE_SCRATCH);
127    if (!pPixmap)
128	return;
129
130    pGCtmp = GetScratchGC(1, pDrawable->pScreen);
131    if (!pGCtmp)
132    {
133	(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
134	return;
135    }
136
137    gcvals[0].val = GXcopy;
138    gcvals[1].val = 1;
139    gcvals[2].val = 0;
140
141    ChangeGC(NullClient, pGCtmp, GCFunction|GCForeground|GCBackground, gcvals);
142
143    nbyLine = BitmapBytePad(width);
144    pbits = malloc(height*nbyLine);
145    if (!pbits)
146    {
147	(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
148	FreeScratchGC(pGCtmp);
149        return;
150    }
151    while(nglyph--)
152    {
153	pci = *ppci++;
154	pglyph = FONTGLYPHBITS(pglyphBase, pci);
155	gWidth = GLYPHWIDTHPIXELS(pci);
156	gHeight = GLYPHHEIGHTPIXELS(pci);
157	if (gWidth && gHeight)
158	{
159	    nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci);
160	    nbyPadGlyph = BitmapBytePad(gWidth);
161
162	    if (nbyGlyphWidth == nbyPadGlyph
163#if GLYPHPADBYTES != 4
164	        && (((int) pglyph) & 3) == 0
165#endif
166		)
167	    {
168		pb = pglyph;
169	    }
170	    else
171	    {
172		for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph))
173		    for (j = 0; j < nbyGlyphWidth; j++)
174			*pb++ = *pglyph++;
175		pb = pbits;
176	    }
177
178	    if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber))
179		ValidateGC((DrawablePtr)pPixmap, pGCtmp);
180	    (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp,
181				pPixmap->drawable.depth,
182				0, 0, gWidth, gHeight,
183				0, XYBitmap, (char *)pb);
184
185	    (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable,
186			       gWidth, gHeight,
187			       x + pci->metrics.leftSideBearing,
188			       y - pci->metrics.ascent);
189	}
190	x += pci->metrics.characterWidth;
191    }
192    (*pDrawable->pScreen->DestroyPixmap)(pPixmap);
193    free(pbits);
194    FreeScratchGC(pGCtmp);
195}
196
197
198void
199miImageGlyphBlt(
200    DrawablePtr pDrawable,
201    GC		*pGC,
202    int		 x,
203    int		 y,
204    unsigned int nglyph,
205    CharInfoPtr *ppci,		/* array of character info */
206    pointer      pglyphBase	/* start of array of glyphs */
207    )
208{
209    ExtentInfoRec info;		/* used by QueryGlyphExtents() */
210    ChangeGCVal gcvals[3];
211    int oldAlu, oldFS;
212    unsigned long	oldFG;
213    xRectangle backrect;
214
215    QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
216
217    if (info.overallWidth >= 0)
218    {
219    	backrect.x = x;
220    	backrect.width = info.overallWidth;
221    }
222    else
223    {
224	backrect.x = x + info.overallWidth;
225	backrect.width = -info.overallWidth;
226    }
227    backrect.y = y - FONTASCENT(pGC->font);
228    backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
229
230    oldAlu = pGC->alu;
231    oldFG = pGC->fgPixel;
232    oldFS = pGC->fillStyle;
233
234    /* fill in the background */
235    gcvals[0].val = GXcopy;
236    gcvals[1].val = pGC->bgPixel;
237    gcvals[2].val = FillSolid;
238    ChangeGC(NullClient, pGC, GCFunction|GCForeground|GCFillStyle, gcvals);
239    ValidateGC(pDrawable, pGC);
240    (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &backrect);
241
242    /* put down the glyphs */
243    gcvals[0].val = oldFG;
244    ChangeGC(NullClient, pGC, GCForeground, gcvals);
245    ValidateGC(pDrawable, pGC);
246    (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
247			      pglyphBase);
248
249    /* put all the toys away when done playing */
250    gcvals[0].val = oldAlu;
251    gcvals[1].val = oldFG;
252    gcvals[2].val = oldFS;
253    ChangeGC(NullClient, pGC, GCFunction|GCForeground|GCFillStyle, gcvals);
254    ValidateGC(pDrawable, pGC);
255
256}
257