Commit | Line | Data |
---|---|---|
4fe1e9dd CT |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This code is derived from software contributed to the Computer Systems | |
6 | * Engineering Group at Lawrence Berkeley Laboratory and to the University | |
7 | * of California at Berkeley by Jef Poskanzer. | |
8 | * | |
9 | * %sccs.include.redist.c% | |
10 | * | |
11 | * @(#)raster_text.c 7.1 (Berkeley) %G% | |
12 | * | |
13 | * from: $Header: raster_text.c,v 1.15 92/06/17 08:14:45 torek Exp $ | |
14 | */ | |
15 | ||
16 | /* | |
17 | * Text routines for raster library. | |
18 | */ | |
19 | ||
20 | #ifdef KERNEL | |
21 | #include "sys/param.h" | |
22 | #include "raster.h" | |
23 | #ifdef COLORFONT_CACHE | |
24 | #include "sys/malloc.h" | |
25 | #define NEW(size) malloc(size, M_DEVBUF, M_NOWAIT) | |
26 | #endif | |
27 | #else | |
28 | #include <sys/types.h> | |
29 | #include "raster.h" | |
30 | #ifdef COLORFONT_CACHE | |
31 | #include <malloc.h> | |
32 | #define NEW(size) malloc(size) | |
33 | #endif | |
34 | #endif | |
35 | ||
36 | ||
37 | /* Draws text. Returns 0 on success, -1 on failure. */ | |
38 | int | |
39 | raster_text( r, x, y, rop, rf, text ) | |
40 | register struct raster* r; | |
41 | int x, y; | |
42 | int rop; | |
43 | struct raster_font* rf; | |
44 | char* text; | |
45 | { | |
46 | return raster_textn( r, x, y, rop, rf, text, strlen( text ) ); | |
47 | } | |
48 | ||
49 | /* Draws n characters of text. Returns 0 on success, -1 on failure. */ | |
50 | int | |
51 | raster_textn( r, x, y, rop, rf, text, n ) | |
52 | register struct raster* r; | |
53 | int x, y; | |
54 | int rop; | |
55 | struct raster_font* rf; | |
56 | char* text; | |
57 | int n; | |
58 | { | |
59 | int clip; | |
60 | int x1, y1; | |
61 | struct raster_char* c; | |
62 | struct raster* charrast; | |
63 | int i; | |
64 | register char ch; | |
65 | int thisx, thisy; | |
66 | int phase; | |
67 | ||
68 | /* Check whether we can avoid clipping. */ | |
69 | clip = 0; | |
70 | if ( rf->flags & RASFONT_FIXEDWIDTH && | |
71 | rf->flags & RASFONT_NOVERTICALMOVEMENT ) | |
72 | { | |
73 | /* This font is well-behaved, we can compute the extent cheaply. */ | |
74 | c = &(rf->chars['@']); | |
75 | charrast = c->r; | |
76 | if ( x + c->homex < 0 || y + c->homey < 0 || | |
77 | x + c->homex + n * c->nextx > r->width || | |
78 | y + c->homey + charrast->height > r->height ) | |
79 | clip = 1; | |
80 | } | |
81 | else | |
82 | { | |
83 | /* Got to step through the string to compute the extent. */ | |
84 | for ( i = 0, x1 = x, y1 = y; | |
85 | i < n; | |
86 | ++i, x1 += c->nextx, y1 += c->nexty ) | |
87 | { | |
88 | c = &(rf->chars[text[i]]); | |
89 | charrast = c->r; | |
90 | if ( charrast != (struct raster*) 0 ) | |
91 | { | |
92 | if ( x1 + c->homex < 0 || y1 + c->homey < 0 || | |
93 | x1 + c->homex + charrast->width > r->width || | |
94 | y1 + c->homey + charrast->height > r->height ) | |
95 | { | |
96 | clip = 1; | |
97 | break; | |
98 | } | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | /* Now display the text. */ | |
104 | for ( i = 0, x1 = x, y1 = y; | |
105 | i < n; | |
106 | ++i, x1 += c->nextx, y1 += c->nexty ) | |
107 | { | |
108 | ch = text[i]; | |
109 | c = &(rf->chars[ch]); | |
110 | charrast = c->r; | |
111 | if ( charrast != (struct raster*) 0 ) | |
112 | { | |
113 | thisx = x1 + c->homex; | |
114 | thisy = y1 + c->homey; | |
115 | ||
116 | phase = 0; | |
117 | #ifdef COLORFONT_CACHE | |
118 | if ( r->depth == 8 ) | |
119 | { | |
120 | /* Initialize color font cache if necessary. */ | |
121 | if ( rf->cache == (struct raster_fontcache*) -1 ) | |
122 | { | |
123 | int c; | |
124 | ||
125 | rf->cache = (struct raster_fontcache*) | |
126 | NEW( sizeof(struct raster_fontcache) ); | |
127 | if ( rf->cache != (struct raster_fontcache*) 0 ) | |
128 | for ( c = 0; c < 256; ++c ) | |
129 | rf->cache->cr[c] = (struct raster*) 0; | |
130 | } | |
131 | ||
132 | if ( rf->cache != (struct raster_fontcache*) 0 ) | |
133 | { | |
134 | int color; | |
135 | struct raster* cr; | |
136 | ||
137 | color = RAS_GETCOLOR( rop ); | |
138 | cr = rf->cache->cr[ch]; | |
139 | /* Is this character cached yet? */ | |
140 | if ( cr != (struct raster*) 0 ) | |
141 | { | |
142 | /* Yes, but is it the right color? */ | |
143 | if ( rf->cache->color[ch] == color ) | |
144 | { | |
145 | /* Yes - switch rasters. */ | |
146 | charrast = cr; | |
147 | } | |
148 | else | |
149 | { | |
150 | /* No, re-draw it. */ | |
151 | if ( raster_op_noclip( | |
152 | cr, 0, 0, charrast->width, | |
153 | charrast->height, rop, charrast, 0, 0 ) == 0 ) | |
154 | { | |
155 | rf->cache->color[ch] = color; | |
156 | charrast = cr; | |
157 | } | |
158 | } | |
159 | } | |
160 | else | |
161 | { | |
162 | /* It's not cached, so cache it. */ | |
163 | cr = raster_alloc( | |
164 | charrast->width, charrast->height, 8 ); | |
165 | if ( cr != (struct raster*) 0 ) | |
166 | if ( raster_op_noclip( | |
167 | cr, 0, 0, charrast->width, charrast->height, | |
168 | rop, charrast, 0, 0 ) == 0 ) | |
169 | { | |
170 | rf->cache->color[ch] = color; | |
171 | charrast = rf->cache->cr[ch] = cr; | |
172 | } | |
173 | } | |
174 | } | |
175 | } | |
176 | #endif /*COLORFONT_CACHE*/ | |
177 | ||
178 | if ( clip ) | |
179 | { | |
180 | if ( raster_op( | |
181 | r, thisx, thisy, charrast->width, charrast->height, | |
182 | rop, charrast, phase, 0 ) < 0 ) | |
183 | return -1; | |
184 | } | |
185 | else | |
186 | { | |
187 | if ( raster_op_noclip( | |
188 | r, thisx, thisy, charrast->width, charrast->height, | |
189 | rop, charrast, phase, 0 ) < 0 ) | |
190 | return -1; | |
191 | } | |
192 | } | |
193 | } | |
194 | ||
195 | return 0; | |
196 | } | |
197 | ||
198 | #ifdef COLORFONT_CACHE | |
199 | /* Allocates a raster. Returns (struct raster*) 0 on failure. */ | |
200 | struct raster* | |
201 | raster_alloc( width, height, depth ) | |
202 | int width, height, depth; | |
203 | { | |
204 | struct raster* r; | |
205 | int linelongs; | |
206 | ||
207 | if ( width <= 0 || height <= 0 || ( depth != 1 && depth != 8 ) ) | |
208 | return (struct raster*) 0; | |
209 | linelongs = ( ( width * depth + 31 ) >> 5 ); | |
210 | r = (struct raster*) | |
211 | NEW( sizeof(struct raster) + height * linelongs * sizeof(u_long)); | |
212 | if ( r == (struct raster*) 0 ) | |
213 | return (struct raster*) 0; | |
214 | ||
215 | r->width = width; | |
216 | r->height = height; | |
217 | r->depth = depth; | |
218 | r->linelongs = linelongs; | |
219 | r->pixels = (u_long*) (r + 1); | |
220 | r->data = (caddr_t) 0; | |
221 | return r; | |
222 | } | |
223 | #endif |