Mercurial > hg > index.fcgi > lj > lj046-2players
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 } |