view src/fontdraw.c @ 1:38c62fded078

initial builds (linux and lj.nds)
author paulo@localhost
date Fri, 13 Mar 2009 01:10:13 -0700
parents
children
line source
1 /*
2 Variable width font drawing library for DS (and GBA)
4 Copyright 2007-2008 Damian Yerrick <pinoandchester@pineight.com>
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.
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:
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.
23 "Source" is the preferred form of a work for making changes to it.
25 */
27 #include <string.h>
28 #include <stdio.h>
29 #include "fontdraw.h"
32 extern const unsigned char vwfont_bin[];
34 typedef struct GlyphRec {
35 unsigned short dataOffset;
36 unsigned char glyphWidth;
37 unsigned char reserved;
38 } GlyphRec;
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
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 }
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 }
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 }
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 }
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 };
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
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;
131 unsigned int x = l;
132 unsigned int stride = v->height * 8;
133 u32 *tile = dst + stride * (l >> 3);
135 if (t < 0) {
136 t = 0;
137 }
138 if (b > v->height * 8) {
139 b = v->height * 8;
140 }
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 }
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 }
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 }
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 }
175 void vwfWinClear(const VWFWindow *w) {
176 size_t nBytes = 32 * w->width * w->height;
177 memset(w->chrBase, 0, nBytes);
178 }
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
187 return dst;
188 }
190 void vwfPutMap(const VWFWindow *w,
191 int l, int t, int r, int b,
192 unsigned int orMask) {
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 }
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 }
214 NAMETABLE *dst = vwfGetMapBase(w->core, w->map);
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 }
225 void vwfWinInit(const VWFWindow *w) {
226 vwfWinClear(w);
227 vwfPutMap(w, 0, 0, w->width, w->height, 0x0000);
228 }
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
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
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 }
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 }
267 // old api emulation
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
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
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 }
302 vwfWinInit(w);
303 }
305 void fontdraw_cls(int sub) {
306 #if ARM9
307 vwfWinClear(sub ? &vwfTouch : &vwfTop);
308 #else
309 vwfWinClear(&vwfTop);
310 #endif
311 }
313 void vwfBlitAligned(const VWFWindow *src, const VWFWindow *dst,
314 int srcX, int srcY, int dstX, int dstY,
315 int w, int h) {
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 }
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 }
359 {
360 const u32 *srcCol = src->chrBase + srcX * src->height * 8 + srcY;
361 u32 *dstCol = dst->chrBase + dstX * dst->height * 8 + dstY;
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 }
372 }