1 /* $NetBSD: raster_text.c,v 1.10 2012/01/31 04:28:03 matt Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to the Computer Systems
8 * Engineering Group at Lawrence Berkeley Laboratory and to the University
9 * of California at Berkeley by Jef Poskanzer.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)raster_text.c 8.1 (Berkeley) 6/11/93
36 */
37
38 /*
39 * Text routines for raster library.
40 */
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: raster_text.c,v 1.10 2012/01/31 04:28:03 matt Exp $");
44
45 #include <sys/param.h>
46 #ifdef _KERNEL
47 #include <sys/systm.h>
48 #include <dev/rcons/raster.h>
49 #ifdef COLORFONT_CACHE
50 #include <sys/malloc.h>
51 #define NEW(size) malloc(size, M_DEVBUF, M_NOWAIT)
52 #endif
53 #else
54 #include <string.h>
55 #include "raster.h"
56 #ifdef COLORFONT_CACHE
57 #include <malloc.h>
58 #define NEW(size) malloc(size)
59 #endif
60 #endif
61
62 /* Draws text. Returns 0 on success, -1 on failure. */
63 int
raster_text(struct raster * r,int x,int y,int rop,struct raster_font * rf,unsigned char * text)64 raster_text(
65 struct raster* r,
66 int x,
67 int y,
68 int rop,
69 struct raster_font* rf,
70 unsigned char* text)
71 {
72 return raster_textn( r, x, y, rop, rf, text, strlen( text ) );
73 }
74
75 /* Draws n characters of text. Returns 0 on success, -1 on failure. */
76 int
raster_textn(struct raster * r,int x,int y,int rop,struct raster_font * rf,unsigned char * text,int n)77 raster_textn(
78 struct raster* r,
79 int x,
80 int y,
81 int rop,
82 struct raster_font* rf,
83 unsigned char* text,
84 int n)
85 {
86 int clip;
87 int x1, y1;
88 struct raster_char* c;
89 struct raster* charrast;
90 int i;
91 unsigned char ch;
92 int thisx, thisy;
93 int phase;
94
95 /* Check whether we can avoid clipping. */
96 clip = 0;
97 if ( rf->flags & RASFONT_FIXEDWIDTH &&
98 rf->flags & RASFONT_NOVERTICALMOVEMENT )
99 {
100 /* This font is well-behaved, we can compute the extent cheaply. */
101 c = &(rf->chars['@']);
102 charrast = c->r;
103 if ( x + c->homex < 0 || y + c->homey < 0 ||
104 x + c->homex + n * c->nextx > r->width ||
105 y + c->homey + charrast->height > r->height )
106 clip = 1;
107 }
108 else
109 {
110 /* Got to step through the string to compute the extent. */
111 for ( i = 0, x1 = x, y1 = y;
112 i < n;
113 ++i, x1 += c->nextx, y1 += c->nexty )
114 {
115 c = &(rf->chars[text[i]]);
116 charrast = c->r;
117 if ( charrast != (struct raster*) 0 )
118 {
119 if ( x1 + c->homex < 0 || y1 + c->homey < 0 ||
120 x1 + c->homex + charrast->width > r->width ||
121 y1 + c->homey + charrast->height > r->height )
122 {
123 clip = 1;
124 break;
125 }
126 }
127 }
128 }
129
130 /* Now display the text. */
131 for ( i = 0, x1 = x, y1 = y;
132 i < n;
133 ++i, x1 += c->nextx, y1 += c->nexty )
134 {
135 ch = text[i];
136 c = &(rf->chars[ch]);
137 charrast = c->r;
138 if ( charrast != (struct raster*) 0 )
139 {
140 thisx = x1 + c->homex;
141 thisy = y1 + c->homey;
142
143 phase = 0;
144 #ifdef COLORFONT_CACHE
145 if ( r->depth == 8 )
146 {
147 /* Initialize color font cache if necessary. */
148 if ( rf->cache == (struct raster_fontcache*) -1 )
149 {
150 int c;
151
152 rf->cache = (struct raster_fontcache*)
153 NEW( sizeof(struct raster_fontcache) );
154 if ( rf->cache != (struct raster_fontcache*) 0 )
155 for ( c = 0; c < 256; ++c )
156 rf->cache->cr[c] = (struct raster*) 0;
157 }
158
159 if ( rf->cache != (struct raster_fontcache*) 0 )
160 {
161 int color;
162 struct raster* cr;
163
164 color = RAS_GETCOLOR( rop );
165 cr = rf->cache->cr[ch];
166 /* Is this character cached yet? */
167 if ( cr != (struct raster*) 0 )
168 {
169 /* Yes, but is it the right color? */
170 if ( rf->cache->color[ch] == color )
171 {
172 /* Yes - switch rasters. */
173 charrast = cr;
174 }
175 else
176 {
177 /* No, re-draw it. */
178 if ( raster_op_noclip(
179 cr, 0, 0, charrast->width,
180 charrast->height, rop, charrast, 0, 0 ) == 0 )
181 {
182 rf->cache->color[ch] = color;
183 charrast = cr;
184 }
185 }
186 }
187 else
188 {
189 /* It's not cached, so cache it. */
190 cr = raster_alloc(
191 charrast->width, charrast->height, 8 );
192 if ( cr != (struct raster*) 0 )
193 if ( raster_op_noclip(
194 cr, 0, 0, charrast->width, charrast->height,
195 rop, charrast, 0, 0 ) == 0 )
196 {
197 rf->cache->color[ch] = color;
198 charrast = rf->cache->cr[ch] = cr;
199 }
200 }
201 }
202 }
203 #endif /*COLORFONT_CACHE*/
204
205 if ( clip )
206 {
207 if ( raster_op(
208 r, thisx, thisy, charrast->width, charrast->height,
209 rop, charrast, phase, 0 ) < 0 )
210 return -1;
211 }
212 else
213 {
214 if ( raster_op_noclip(
215 r, thisx, thisy, charrast->width, charrast->height,
216 rop, charrast, phase, 0 ) < 0 )
217 return -1;
218 }
219 }
220 }
221
222 return 0;
223 }
224
225 #ifdef COLORFONT_CACHE
226 /* Allocates a raster. Returns (struct raster*) 0 on failure. */
227 struct raster*
raster_alloc(int width,int height,int depth)228 raster_alloc(
229 int width,
230 int height,
231 int depth)
232 {
233 struct raster* r;
234 int linelongs;
235
236 if ( width <= 0 || height <= 0 || ( depth != 1 && depth != 8 ) )
237 return (struct raster*) 0;
238 linelongs = ( ( width * depth + 31 ) >> 5 );
239 r = (struct raster*)
240 NEW( sizeof(struct raster) + height * linelongs * sizeof(u_int32_t));
241 if ( r == (struct raster*) 0 )
242 return (struct raster*) 0;
243
244 r->width = width;
245 r->height = height;
246 r->depth = depth;
247 r->linelongs = linelongs;
248 r->pixels = (u_int32_t*) (r + 1);
249 r->data = (void *) 0;
250 return r;
251 }
252 #endif
253