Mercurial > hg > index.fcgi > lj > lj046
diff src/fontdraw.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/fontdraw.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,372 @@ 1.4 +/* 1.5 +Variable width font drawing library for DS (and GBA) 1.6 + 1.7 +Copyright 2007-2008 Damian Yerrick <pinoandchester@pineight.com> 1.8 + 1.9 +This work is provided 'as-is', without any express or implied 1.10 +warranty. In no event will the authors be held liable for any 1.11 +damages arising from the use of this work. 1.12 + 1.13 +Permission is granted to anyone to use this work for any purpose, 1.14 +including commercial applications, and to alter it and redistribute 1.15 +it freely, subject to the following restrictions: 1.16 + 1.17 +1. The origin of this work must not be misrepresented; you must 1.18 + not claim that you wrote the original work. If you use 1.19 + this work in a product, an acknowledgment in the product 1.20 + documentation would be appreciated but is not required. 1.21 +2. Altered source versions must be plainly marked as such, and must 1.22 + not be misrepresented as being the original work. 1.23 +3. This notice may not be removed or altered from any source 1.24 + distribution. 1.25 + 1.26 +"Source" is the preferred form of a work for making changes to it. 1.27 + 1.28 +*/ 1.29 + 1.30 +#include <string.h> 1.31 +#include <stdio.h> 1.32 +#include "fontdraw.h" 1.33 + 1.34 + 1.35 +extern const unsigned char vwfont_bin[]; 1.36 + 1.37 +typedef struct GlyphRec { 1.38 + unsigned short dataOffset; 1.39 + unsigned char glyphWidth; 1.40 + unsigned char reserved; 1.41 +} GlyphRec; 1.42 + 1.43 +#ifndef FONTDRAW_SPLIT_COMPILE 1.44 +#include "fontdraw_engine.c" 1.45 +#else 1.46 +__attribute__((long_call)) 1.47 +unsigned int fontdraw_putchar(u32 *dst, unsigned int colStride, int wid, int x, int glyph); 1.48 +__attribute__((long_call)) 1.49 +void vwfRectfillColumn(u32 *dst, unsigned int colStride, 1.50 + unsigned int l, unsigned int t, 1.51 + unsigned int r, unsigned int b, 1.52 + unsigned int c); 1.53 +#endif 1.54 + 1.55 + 1.56 +unsigned int fontdraw_charWidth(int glyph) { 1.57 + glyph &= 0xFF; 1.58 + if (glyph < vwfont_bin[1]) { 1.59 + return 0; 1.60 + } 1.61 + glyph -= vwfont_bin[1]; 1.62 + if (vwfont_bin[2] != 0 && glyph >= vwfont_bin[2]) { 1.63 + return 0; 1.64 + } 1.65 + const GlyphRec *glyphRec = 1.66 + ((const GlyphRec *)(vwfont_bin + vwfont_bin[0])) + glyph; 1.67 + return glyphRec->glyphWidth; 1.68 +} 1.69 + 1.70 +unsigned int fontdraw_strWidth(const char *s) { 1.71 + unsigned int width = 0; 1.72 + for (; *s; ++s) { 1.73 + width += fontdraw_charWidth(*s); 1.74 + } 1.75 + return width; 1.76 +} 1.77 + 1.78 +size_t fontdraw_cutStr(const char *s, int targetWidth) { 1.79 + size_t len; 1.80 + for (len = 0; s[len]; ++len) { 1.81 + int charWidth = fontdraw_charWidth(s[len]); 1.82 + if (charWidth > targetWidth) { 1.83 + return len; 1.84 + } 1.85 + targetWidth -= charWidth; 1.86 + } 1.87 + return len; 1.88 +} 1.89 + 1.90 +static unsigned int fontdraw_putline(u32 *dst, unsigned int colStride, int wid, int x, const char *src) { 1.91 + unsigned int startX = x; 1.92 + for (int c = *src; c != 0 && wid > 0; c = *++src) { 1.93 + int chWidth = fontdraw_putchar(dst, colStride, wid, x, c & 0xFF); 1.94 + x += chWidth; 1.95 + wid -= chWidth; 1.96 + } 1.97 + return x - startX; 1.98 +} 1.99 + 1.100 +#ifdef ARM9 1.101 +const VWFWindow vwfTop = { 1.102 + .left = 0, .top = 0, .width = 32, .height = 24, 1.103 + .chrBase = (u32 *)BG_TILE_RAM(0), 1.104 + .map = 31, 1.105 + .core = 0, 1.106 + .mapTileBase = 0 1.107 +}; 1.108 + 1.109 +const VWFWindow vwfTouch = { 1.110 + .left = 0, .top = 0, .width = 32, .height = 24, 1.111 + .chrBase = (u32 *)BG_TILE_RAM_SUB(0), 1.112 + .map = 31, 1.113 + .core = 1, 1.114 + .mapTileBase = 0 1.115 +}; 1.116 +#else 1.117 +const VWFWindow vwfTop = { 1.118 + .left = 0, .top = 0, .width = 30, .height = 20, 1.119 + .chrBase = (u32 *)PATRAM4(0, 0), 1.120 + .map = 31, 1.121 + .core = 0, 1.122 + .mapTileBase = 0 1.123 +}; 1.124 +#endif 1.125 + 1.126 +void vwfRectfill(const VWFWindow *v, int l, int t, int r, int b, int c) 1.127 +{ 1.128 + u32 *dst = v->chrBase; 1.129 + c &= 0x0000000F; 1.130 + c |= c << 4; 1.131 + c |= c << 8; 1.132 + c |= c << 16; 1.133 + 1.134 + unsigned int x = l; 1.135 + unsigned int stride = v->height * 8; 1.136 + u32 *tile = dst + stride * (l >> 3); 1.137 + 1.138 + if (t < 0) { 1.139 + t = 0; 1.140 + } 1.141 + if (b > v->height * 8) { 1.142 + b = v->height * 8; 1.143 + } 1.144 + 1.145 + for(x = l; x < r; x = (x + 8) & -8) { 1.146 + vwfRectfillColumn(tile, stride, x & 7, t, 1.147 + (r & -8) > (x & -8) ? 8 : (r & 7), 1.148 + b, c); 1.149 + tile += stride; 1.150 + } 1.151 +} 1.152 + 1.153 +void vwfHline(const VWFWindow *v, int l, int t, int r, int c) { 1.154 + if (r < l) { 1.155 + int temp = l; 1.156 + l = r; 1.157 + r = temp; 1.158 + } 1.159 + vwfRectfill(v, l, t, r, t + 1, c); 1.160 +} 1.161 + 1.162 +void vwfVline(const VWFWindow *v, int l, int t, int b, int c) { 1.163 + if (b < t) { 1.164 + int temp = t; 1.165 + t = b; 1.166 + b = temp; 1.167 + } 1.168 + vwfRectfill(v, l, t, l + 1, b, c); 1.169 +} 1.170 + 1.171 +void vwfRect(const VWFWindow *v, int l, int t, int r, int b, int c) { 1.172 + vwfVline(v, l, t, b, c); 1.173 + vwfVline(v, r - 1, t, b, c); 1.174 + vwfHline(v, l, t, r, c); 1.175 + vwfHline(v, l, b - 1, r, c); 1.176 +} 1.177 + 1.178 +void vwfWinClear(const VWFWindow *w) { 1.179 + size_t nBytes = 32 * w->width * w->height; 1.180 + memset(w->chrBase, 0, nBytes); 1.181 +} 1.182 + 1.183 +static inline NAMETABLE *vwfGetMapBase(int core, int map) { 1.184 +#if ARM9 1.185 + NAMETABLE *dst = core ? &(MAP_SUB[map]) : &(MAP[map]); 1.186 +#else 1.187 + NAMETABLE *dst = &(MAP[map]); 1.188 +#endif 1.189 + 1.190 + return dst; 1.191 +} 1.192 + 1.193 +void vwfPutMap(const VWFWindow *w, 1.194 + int l, int t, int r, int b, 1.195 + unsigned int orMask) { 1.196 + 1.197 + if (r > (int)w->width) { 1.198 + r = (int)w->width; 1.199 + } 1.200 + if (l < 0) { 1.201 + l = 0; 1.202 + } 1.203 + if (r <= l) { 1.204 + return; 1.205 + } 1.206 + 1.207 + if (b > (int)w->height) { 1.208 + b = (int)w->height; 1.209 + } 1.210 + if (t < 0) { 1.211 + t = 0; 1.212 + } 1.213 + if (b <= t) { 1.214 + return; 1.215 + } 1.216 + 1.217 + NAMETABLE *dst = vwfGetMapBase(w->core, w->map); 1.218 + 1.219 + int mapTile = (w->mapTileBase + w->height * l + t) | orMask; 1.220 + for (int x = w->left + l; x < w->left + r; ++x) { 1.221 + for (int y = w->top + t; y < w->top + b; ++y) { 1.222 + (*dst)[y][x] = mapTile++; 1.223 + } 1.224 + mapTile += w->height + t - b; 1.225 + } 1.226 +} 1.227 + 1.228 +void vwfWinInit(const VWFWindow *w) { 1.229 + vwfWinClear(w); 1.230 + vwfPutMap(w, 0, 0, w->width, w->height, 0x0000); 1.231 +} 1.232 + 1.233 +#if 0 1.234 +void vwfWinInit(const VWFWindow *w) { 1.235 +#if ARM9 1.236 + NAMETABLE *dst = w->core ? &(MAP_SUB[w->map]) : &(MAP[w->map]); 1.237 +#else 1.238 + NAMETABLE *dst = &(MAP[w->map]); 1.239 +#endif 1.240 + 1.241 + int mapTile = w->mapTileBase; 1.242 + for (int x = w->left; x < w->left + w->width; ++x) { 1.243 + for (int y = w->top; y < w->top + w->height; ++y) { 1.244 + (*dst)[y][x] = mapTile++; 1.245 + } 1.246 + } 1.247 + vwfWinClear(w); 1.248 +} 1.249 +#endif 1.250 + 1.251 +unsigned int vwfPuts(const VWFWindow *w, 1.252 + const char *str, 1.253 + int x, int y) { 1.254 + return fontdraw_putline(w->chrBase + y, 8 * w->height, 1.255 + w->width * 8 - x, x, str); 1.256 +} 1.257 + 1.258 +unsigned int vwfPutc(const VWFWindow *w, 1.259 + int c, 1.260 + int x, int y) { 1.261 + int width = 8 * w->width - x; 1.262 + if (width >= fontdraw_charWidth(c)) { 1.263 + return fontdraw_putchar(w->chrBase + y, 8 * w->height, 1.264 + w->width * 8 - x, x, c & 0xFF); 1.265 + } else { 1.266 + return 0; 1.267 + } 1.268 +} 1.269 + 1.270 +// old api emulation 1.271 + 1.272 +#if 0 1.273 +void fontdraw_demo_putline(int x, int y, const char *str) { 1.274 + const VWFWindow *w = &vwfTop; 1.275 +#if ARM9 1.276 + if (y >= 288) { 1.277 + w = &vwfTouch; 1.278 + y -= 288; 1.279 + } 1.280 +#endif 1.281 + vwfPuts(w, str, x, y); 1.282 +} 1.283 +#endif 1.284 + 1.285 +void fontdraw_setupVRAM(int sub) { 1.286 +#if ARM9 1.287 + const VWFWindow *w = sub ? &vwfTouch : &vwfTop; 1.288 +#else 1.289 + const VWFWindow *w = &vwfTop; 1.290 +#endif 1.291 + 1.292 +#if ARM9 1.293 + if (sub == 0) { 1.294 + BGCTRL_SUB[0] = BG_MAP_BASE(31) | BG_TILE_BASE(0); 1.295 + BG_OFFSET_SUB[0].x = 0; 1.296 + BG_OFFSET_SUB[0].y = 0; 1.297 + } else 1.298 +#endif 1.299 + { 1.300 + BGCTRL[0] = BG_MAP_BASE(31) | BG_TILE_BASE(0); 1.301 + BG_OFFSET[0].x = 0; 1.302 + BG_OFFSET[0].y = 0; 1.303 + } 1.304 + 1.305 + vwfWinInit(w); 1.306 +} 1.307 + 1.308 +void fontdraw_cls(int sub) { 1.309 +#if ARM9 1.310 + vwfWinClear(sub ? &vwfTouch : &vwfTop); 1.311 +#else 1.312 + vwfWinClear(&vwfTop); 1.313 +#endif 1.314 +} 1.315 + 1.316 +void vwfBlitAligned(const VWFWindow *src, const VWFWindow *dst, 1.317 + int srcX, int srcY, int dstX, int dstY, 1.318 + int w, int h) { 1.319 + 1.320 + /* Clip in X */ 1.321 + if (srcX < 0) { 1.322 + dstX -= srcX; 1.323 + w -= srcX; 1.324 + srcX = 0; 1.325 + } 1.326 + if (dstX < 0) { 1.327 + srcX -= dstX; 1.328 + w -= dstX; 1.329 + dstX = 0; 1.330 + } 1.331 + if (srcX + w > (int)src->width) { 1.332 + w = src->width - srcX; 1.333 + } 1.334 + if (dstX + w > (int)dst->width) { 1.335 + w = dst->width - dstX; 1.336 + } 1.337 + if (w <= 0) { 1.338 + return; 1.339 + } 1.340 + 1.341 + /* Clip in Y */ 1.342 + if (srcY < 0) { 1.343 + dstY -= srcY; 1.344 + h -= srcY; 1.345 + srcY = 0; 1.346 + } 1.347 + if (dstY < 0) { 1.348 + srcY -= dstY; 1.349 + h -= dstY; 1.350 + dstY = 0; 1.351 + } 1.352 + if (srcY + h > src->height * 8) { 1.353 + h = src->height * 8 - srcY; 1.354 + } 1.355 + if (dstX + w > dst->height * 8) { 1.356 + h = dst->height * 8 - dstY; 1.357 + } 1.358 + if (h < 0) { 1.359 + return; 1.360 + } 1.361 + 1.362 + { 1.363 + const u32 *srcCol = src->chrBase + srcX * src->height * 8 + srcY; 1.364 + u32 *dstCol = dst->chrBase + dstX * dst->height * 8 + dstY; 1.365 + 1.366 + for (; w > 0; --w) { 1.367 + for (unsigned int y = 0; y < h; ++y) { 1.368 + dstCol[y] = srcCol[y]; 1.369 + } 1.370 + srcCol += src->height * 8; 1.371 + dstCol += dst->height * 8; 1.372 + } 1.373 + } 1.374 + 1.375 +}