annotate src/fontdraw.c @ 0:c84446dfb3f5

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