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 "misc.h"
54#include <X11/fonts/fontstruct.h>
55#include "dixfontstr.h"
56#include "scrnintstr.h"
57#include "gcstruct.h"
58#include "resource.h"
59#include "dix.h"
60#include "cursorstr.h"
61#include "opaque.h"
62#include "servermd.h"
63
64
65/*
66    get the bits out of the font in a portable way.  to avoid
67dealing with padding and such-like, we draw the glyph into
68a bitmap, then read the bits out with GetImage, which
69uses server-natural format.
70    since all screens return the same bitmap format, we'll just use
71the first one we find.
72    the character origin lines up with the hotspot in the
73cursor metrics.
74*/
75
76int
77ServerBitsFromGlyph(FontPtr pfont, unsigned ch, CursorMetricPtr cm, unsigned char **ppbits)
78{
79    ScreenPtr pScreen;
80    GCPtr pGC;
81    xRectangle rect;
82    PixmapPtr ppix;
83    long nby;
84    char *pbits;
85    ChangeGCVal gcval[3];
86    unsigned char char2b[2];
87
88    /* turn glyph index into a protocol-format char2b */
89    char2b[0] = (unsigned char)(ch >> 8);
90    char2b[1] = (unsigned char)(ch & 0xff);
91
92    pScreen = screenInfo.screens[0];
93    nby = BitmapBytePad(cm->width) * (long)cm->height;
94    pbits = calloc(1, nby);
95    if (!pbits)
96	return BadAlloc;
97
98    ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width,
99					       cm->height, 1,
100					       CREATE_PIXMAP_USAGE_SCRATCH);
101    pGC = GetScratchGC(1, pScreen);
102    if (!ppix || !pGC)
103    {
104	if (ppix)
105	    (*pScreen->DestroyPixmap)(ppix);
106	if (pGC)
107	    FreeScratchGC(pGC);
108	free(pbits);
109	return BadAlloc;
110    }
111
112    rect.x = 0;
113    rect.y = 0;
114    rect.width = cm->width;
115    rect.height = cm->height;
116
117    /* fill the pixmap with 0 */
118    gcval[0].val = GXcopy;
119    gcval[1].val = 0;
120    gcval[2].ptr = (pointer)pfont;
121    ChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont, gcval);
122    ValidateGC((DrawablePtr)ppix, pGC);
123    (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect);
124
125    /* draw the glyph */
126    gcval[0].val = 1;
127    ChangeGC(NullClient, pGC, GCForeground, gcval);
128    ValidateGC((DrawablePtr)ppix, pGC);
129    (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot,
130			    1, (unsigned short *)char2b);
131    (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height,
132			 XYPixmap, 1, pbits);
133    *ppbits = (unsigned char *)pbits;
134    FreeScratchGC(pGC);
135    (*pScreen->DestroyPixmap)(ppix);
136    return Success;
137}
138
139
140Bool
141CursorMetricsFromGlyph(FontPtr pfont, unsigned ch, CursorMetricPtr cm)
142{
143    CharInfoPtr 	pci;
144    unsigned long	nglyphs;
145    CARD8		chs[2];
146    FontEncoding	encoding;
147
148    chs[0] = ch >> 8;
149    chs[1] = ch;
150    encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit;
151    if (encoding == Linear16Bit)
152    {
153	if (ch < pfont->info.firstCol || pfont->info.lastCol < ch)
154	    return FALSE;
155    }
156    else
157    {
158	if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0])
159	    return FALSE;
160	if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1])
161	    return FALSE;
162    }
163    (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci);
164    if (nglyphs == 0)
165	return FALSE;
166    cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
167    cm->height = pci->metrics.descent + pci->metrics.ascent;
168    if (pci->metrics.leftSideBearing > 0)
169    {
170	cm->width += pci->metrics.leftSideBearing;
171	cm->xhot = 0;
172    }
173    else
174    {
175	cm->xhot = -pci->metrics.leftSideBearing;
176	if (pci->metrics.rightSideBearing < 0)
177	    cm->width -= pci->metrics.rightSideBearing;
178    }
179    if (pci->metrics.ascent < 0)
180    {
181	cm->height -= pci->metrics.ascent;
182	cm->yhot = 0;
183    }
184    else
185    {
186	cm->yhot = pci->metrics.ascent;
187	if (pci->metrics.descent < 0)
188	    cm->height -= pci->metrics.descent;
189    }
190    return TRUE;
191}
192