1/*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include "glxserver.h"
36#include "glxutil.h"
37#include "unpack.h"
38#include "glapitable.h"
39#include "glapi.h"
40#include "glthread.h"
41#include "dispatch.h"
42#include "indirect_dispatch.h"
43#include <GL/gl.h>
44#include <pixmapstr.h>
45#include <windowstr.h>
46#include <dixfontstr.h>
47
48/*
49** Make a single GL bitmap from a single X glyph
50*/
51static int __glXMakeBitmapFromGlyph(FontPtr font, CharInfoPtr pci)
52{
53    int i, j;
54    int widthPadded;	/* width of glyph in bytes, as padded by X */
55    int allocBytes;	/* bytes to allocate to store bitmap */
56    int w;		/* width of glyph in bits */
57    int h;		/* height of glyph */
58    register unsigned char *pglyph;
59    register unsigned char *p;
60    unsigned char *allocbuf;
61#define __GL_CHAR_BUF_SIZE 2048
62    unsigned char buf[__GL_CHAR_BUF_SIZE];
63
64    w = GLYPHWIDTHPIXELS(pci);
65    h = GLYPHHEIGHTPIXELS(pci);
66    widthPadded = GLYPHWIDTHBYTESPADDED(pci);
67
68    /*
69    ** Use the local buf if possible, otherwise malloc.
70    */
71    allocBytes = widthPadded * h;
72    if (allocBytes <= __GL_CHAR_BUF_SIZE) {
73	p = buf;
74	allocbuf = 0;
75    } else {
76	p = (unsigned char *) malloc(allocBytes);
77	if (!p)
78	    return BadAlloc;
79	allocbuf = p;
80    }
81
82    /*
83    ** We have to reverse the picture, top to bottom
84    */
85
86    pglyph = FONTGLYPHBITS(FONTGLYPHS(font), pci) + (h-1)*widthPadded;
87    for (j=0; j < h; j++) {
88	for (i=0; i < widthPadded; i++) {
89	    p[i] = pglyph[i];
90	}
91	pglyph -= widthPadded;
92	p += widthPadded;
93    }
94    CALL_Bitmap( GET_DISPATCH(), (w, h, -pci->metrics.leftSideBearing,
95				  pci->metrics.descent,
96				  pci->metrics.characterWidth, 0,
97				  allocbuf ? allocbuf : buf) );
98
99    free(allocbuf);
100    return Success;
101#undef __GL_CHAR_BUF_SIZE
102}
103
104/*
105** Create a GL bitmap for each character in the X font.  The bitmap is stored
106** in a display list.
107*/
108
109static int
110MakeBitmapsFromFont(FontPtr pFont, int first, int count, int list_base)
111{
112    unsigned long   i, nglyphs;
113    CARD8	    chs[2];		/* the font index we are going after */
114    CharInfoPtr	    pci;
115    int rv;				/* return value */
116    int encoding = (FONTLASTROW(pFont) == 0) ? Linear16Bit : TwoD16Bit;
117
118    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, FALSE) );
119    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, BITMAP_BIT_ORDER == LSBFirst) );
120    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, 0) );
121    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
122    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
123    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, GLYPHPADBYTES) );
124    for (i=0; i < count; i++) {
125	chs[0] = (first + i) >> 8;	/* high byte is first byte */
126	chs[1] = first + i;
127
128	(*pFont->get_glyphs)(pFont, 1, chs, (FontEncoding)encoding,
129		&nglyphs, &pci);
130
131	/*
132	** Define a display list containing just a glBitmap() call.
133	*/
134	CALL_NewList( GET_DISPATCH(), (list_base + i, GL_COMPILE) );
135	if (nglyphs ) {
136	    rv = __glXMakeBitmapFromGlyph(pFont, pci);
137	    if (rv) {
138		return rv;
139	    }
140	}
141	CALL_EndList( GET_DISPATCH(), () );
142    }
143    return Success;
144}
145
146/************************************************************************/
147
148int __glXDisp_UseXFont(__GLXclientState *cl, GLbyte *pc)
149{
150    ClientPtr client = cl->client;
151    xGLXUseXFontReq *req;
152    FontPtr pFont;
153    GLuint currentListIndex;
154    __GLXcontext *cx;
155    int error;
156
157    REQUEST_SIZE_MATCH(xGLXUseXFontReq);
158
159    req = (xGLXUseXFontReq *) pc;
160    cx = __glXForceCurrent(cl, req->contextTag, &error);
161    if (!cx) {
162	return error;
163    }
164
165    CALL_GetIntegerv( GET_DISPATCH(), (GL_LIST_INDEX, (GLint*) &currentListIndex) );
166    if (currentListIndex != 0) {
167	/*
168	** A display list is currently being made.  It is an error
169	** to try to make a font during another lists construction.
170	*/
171	client->errorValue = cx->id;
172	return __glXError(GLXBadContextState);
173    }
174
175    /*
176    ** Font can actually be either the ID of a font or the ID of a GC
177    ** containing a font.
178    */
179
180    error = dixLookupFontable(&pFont, req->font, client, DixReadAccess);
181    if (error != Success)
182	return error;
183
184    return MakeBitmapsFromFont(pFont, req->first, req->count,
185				    req->listBase);
186}
187