comparison src/fontdraw.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b846cba9e945
1 /*
2 Variable width font drawing library for DS (and GBA)
3
4 Copyright 2007-2008 Damian Yerrick <pinoandchester@pineight.com>
5
6 This work is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any
8 damages arising from the use of this work.
9
10 Permission is granted to anyone to use this work for any purpose,
11 including commercial applications, and to alter it and redistribute
12 it freely, subject to the following restrictions:
13
14 1. The origin of this work must not be misrepresented; you must
15 not claim that you wrote the original work. If you use
16 this work in a product, an acknowledgment in the product
17 documentation would be appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must
19 not be misrepresented as being the original work.
20 3. This notice may not be removed or altered from any source
21 distribution.
22
23 "Source" is the preferred form of a work for making changes to it.
24
25 */
26
27 #include <string.h>
28 #include <stdio.h>
29 #include "fontdraw.h"
30
31
32 extern const unsigned char vwfont_bin[];
33
34 typedef struct GlyphRec {
35 unsigned short dataOffset;
36 unsigned char glyphWidth;
37 unsigned char reserved;
38 } GlyphRec;
39
40 #ifndef FONTDRAW_SPLIT_COMPILE
41 #include "fontdraw_engine.c"
42 #else
43 __attribute__((long_call))
44 unsigned int fontdraw_putchar(u32 *dst, unsigned int colStride, int wid, int x, int glyph);
45 __attribute__((long_call))
46 void vwfRectfillColumn(u32 *dst, unsigned int colStride,
47 unsigned int l, unsigned int t,
48 unsigned int r, unsigned int b,
49 unsigned int c);
50 #endif
51
52
53 unsigned int fontdraw_charWidth(int glyph) {
54 glyph &= 0xFF;
55 if (glyph < vwfont_bin[1]) {
56 return 0;
57 }
58 glyph -= vwfont_bin[1];
59 if (vwfont_bin[2] != 0 && glyph >= vwfont_bin[2]) {
60 return 0;
61 }
62 const GlyphRec *glyphRec =
63 ((const GlyphRec *)(vwfont_bin + vwfont_bin[0])) + glyph;
64 return glyphRec->glyphWidth;
65 }
66
67 unsigned int fontdraw_strWidth(const char *s) {
68 unsigned int width = 0;
69 for (; *s; ++s) {
70 width += fontdraw_charWidth(*s);
71 }
72 return width;
73 }
74
75 size_t fontdraw_cutStr(const char *s, int targetWidth) {
76 size_t len;
77 for (len = 0; s[len]; ++len) {
78 int charWidth = fontdraw_charWidth(s[len]);
79 if (charWidth > targetWidth) {
80 return len;
81 }
82 targetWidth -= charWidth;
83 }
84 return len;
85 }
86
87 static unsigned int fontdraw_putline(u32 *dst, unsigned int colStride, int wid, int x, const char *src) {
88 unsigned int startX = x;
89 for (int c = *src; c != 0 && wid > 0; c = *++src) {
90 int chWidth = fontdraw_putchar(dst, colStride, wid, x, c & 0xFF);
91 x += chWidth;
92 wid -= chWidth;
93 }
94 return x - startX;
95 }
96
97 #ifdef ARM9
98 const VWFWindow vwfTop = {
99 .left = 0, .top = 0, .width = 32, .height = 24,
100 .chrBase = (u32 *)BG_TILE_RAM(0),
101 .map = 31,
102 .core = 0,
103 .mapTileBase = 0
104 };
105
106 const VWFWindow vwfTouch = {
107 .left = 0, .top = 0, .width = 32, .height = 24,
108 .chrBase = (u32 *)BG_TILE_RAM_SUB(0),
109 .map = 31,
110 .core = 1,
111 .mapTileBase = 0
112 };
113 #else
114 const VWFWindow vwfTop = {
115 .left = 0, .top = 0, .width = 30, .height = 20,
116 .chrBase = (u32 *)PATRAM4(0, 0),
117 .map = 31,
118 .core = 0,
119 .mapTileBase = 0
120 };
121 #endif
122
123 void vwfRectfill(const VWFWindow *v, int l, int t, int r, int b, int c)
124 {
125 u32 *dst = v->chrBase;
126 c &= 0x0000000F;
127 c |= c << 4;
128 c |= c << 8;
129 c |= c << 16;
130
131 unsigned int x = l;
132 unsigned int stride = v->height * 8;
133 u32 *tile = dst + stride * (l >> 3);
134
135 if (t < 0) {
136 t = 0;
137 }
138 if (b > v->height * 8) {
139 b = v->height * 8;
140 }
141
142 for(x = l; x < r; x = (x + 8) & -8) {
143 vwfRectfillColumn(tile, stride, x & 7, t,
144 (r & -8) > (x & -8) ? 8 : (r & 7),
145 b, c);
146 tile += stride;
147 }
148 }
149
150 void vwfHline(const VWFWindow *v, int l, int t, int r, int c) {
151 if (r < l) {
152 int temp = l;
153 l = r;
154 r = temp;
155 }
156 vwfRectfill(v, l, t, r, t + 1, c);
157 }
158
159 void vwfVline(const VWFWindow *v, int l, int t, int b, int c) {
160 if (b < t) {
161 int temp = t;
162 t = b;
163 b = temp;
164 }
165 vwfRectfill(v, l, t, l + 1, b, c);
166 }
167
168 void vwfRect(const VWFWindow *v, int l, int t, int r, int b, int c) {
169 vwfVline(v, l, t, b, c);
170 vwfVline(v, r - 1, t, b, c);
171 vwfHline(v, l, t, r, c);
172 vwfHline(v, l, b - 1, r, c);
173 }
174
175 void vwfWinClear(const VWFWindow *w) {
176 size_t nBytes = 32 * w->width * w->height;
177 memset(w->chrBase, 0, nBytes);
178 }
179
180 static inline NAMETABLE *vwfGetMapBase(int core, int map) {
181 #if ARM9
182 NAMETABLE *dst = core ? &(MAP_SUB[map]) : &(MAP[map]);
183 #else
184 NAMETABLE *dst = &(MAP[map]);
185 #endif
186
187 return dst;
188 }
189
190 void vwfPutMap(const VWFWindow *w,
191 int l, int t, int r, int b,
192 unsigned int orMask) {
193
194 if (r > (int)w->width) {
195 r = (int)w->width;
196 }
197 if (l < 0) {
198 l = 0;
199 }
200 if (r <= l) {
201 return;
202 }
203
204 if (b > (int)w->height) {
205 b = (int)w->height;
206 }
207 if (t < 0) {
208 t = 0;
209 }
210 if (b <= t) {
211 return;
212 }
213
214 NAMETABLE *dst = vwfGetMapBase(w->core, w->map);
215
216 int mapTile = (w->mapTileBase + w->height * l + t) | orMask;
217 for (int x = w->left + l; x < w->left + r; ++x) {
218 for (int y = w->top + t; y < w->top + b; ++y) {
219 (*dst)[y][x] = mapTile++;
220 }
221 mapTile += w->height + t - b;
222 }
223 }
224
225 void vwfWinInit(const VWFWindow *w) {
226 vwfWinClear(w);
227 vwfPutMap(w, 0, 0, w->width, w->height, 0x0000);
228 }
229
230 #if 0
231 void vwfWinInit(const VWFWindow *w) {
232 #if ARM9
233 NAMETABLE *dst = w->core ? &(MAP_SUB[w->map]) : &(MAP[w->map]);
234 #else
235 NAMETABLE *dst = &(MAP[w->map]);
236 #endif
237
238 int mapTile = w->mapTileBase;
239 for (int x = w->left; x < w->left + w->width; ++x) {
240 for (int y = w->top; y < w->top + w->height; ++y) {
241 (*dst)[y][x] = mapTile++;
242 }
243 }
244 vwfWinClear(w);
245 }
246 #endif
247
248 unsigned int vwfPuts(const VWFWindow *w,
249 const char *str,
250 int x, int y) {
251 return fontdraw_putline(w->chrBase + y, 8 * w->height,
252 w->width * 8 - x, x, str);
253 }
254
255 unsigned int vwfPutc(const VWFWindow *w,
256 int c,
257 int x, int y) {
258 int width = 8 * w->width - x;
259 if (width >= fontdraw_charWidth(c)) {
260 return fontdraw_putchar(w->chrBase + y, 8 * w->height,
261 w->width * 8 - x, x, c & 0xFF);
262 } else {
263 return 0;
264 }
265 }
266
267 // old api emulation
268
269 #if 0
270 void fontdraw_demo_putline(int x, int y, const char *str) {
271 const VWFWindow *w = &vwfTop;
272 #if ARM9
273 if (y >= 288) {
274 w = &vwfTouch;
275 y -= 288;
276 }
277 #endif
278 vwfPuts(w, str, x, y);
279 }
280 #endif
281
282 void fontdraw_setupVRAM(int sub) {
283 #if ARM9
284 const VWFWindow *w = sub ? &vwfTouch : &vwfTop;
285 #else
286 const VWFWindow *w = &vwfTop;
287 #endif
288
289 #if ARM9
290 if (sub == 0) {
291 BGCTRL_SUB[0] = BG_MAP_BASE(31) | BG_TILE_BASE(0);
292 BG_OFFSET_SUB[0].x = 0;
293 BG_OFFSET_SUB[0].y = 0;
294 } else
295 #endif
296 {
297 BGCTRL[0] = BG_MAP_BASE(31) | BG_TILE_BASE(0);
298 BG_OFFSET[0].x = 0;
299 BG_OFFSET[0].y = 0;
300 }
301
302 vwfWinInit(w);
303 }
304
305 void fontdraw_cls(int sub) {
306 #if ARM9
307 vwfWinClear(sub ? &vwfTouch : &vwfTop);
308 #else
309 vwfWinClear(&vwfTop);
310 #endif
311 }
312
313 void vwfBlitAligned(const VWFWindow *src, const VWFWindow *dst,
314 int srcX, int srcY, int dstX, int dstY,
315 int w, int h) {
316
317 /* Clip in X */
318 if (srcX < 0) {
319 dstX -= srcX;
320 w -= srcX;
321 srcX = 0;
322 }
323 if (dstX < 0) {
324 srcX -= dstX;
325 w -= dstX;
326 dstX = 0;
327 }
328 if (srcX + w > (int)src->width) {
329 w = src->width - srcX;
330 }
331 if (dstX + w > (int)dst->width) {
332 w = dst->width - dstX;
333 }
334 if (w <= 0) {
335 return;
336 }
337
338 /* Clip in Y */
339 if (srcY < 0) {
340 dstY -= srcY;
341 h -= srcY;
342 srcY = 0;
343 }
344 if (dstY < 0) {
345 srcY -= dstY;
346 h -= dstY;
347 dstY = 0;
348 }
349 if (srcY + h > src->height * 8) {
350 h = src->height * 8 - srcY;
351 }
352 if (dstX + w > dst->height * 8) {
353 h = dst->height * 8 - dstY;
354 }
355 if (h < 0) {
356 return;
357 }
358
359 {
360 const u32 *srcCol = src->chrBase + srcX * src->height * 8 + srcY;
361 u32 *dstCol = dst->chrBase + dstX * dst->height * 8 + dstY;
362
363 for (; w > 0; --w) {
364 for (unsigned int y = 0; y < h; ++y) {
365 dstCol[y] = srcCol[y];
366 }
367 srcCol += src->height * 8;
368 dstCol += dst->height * 8;
369 }
370 }
371
372 }