Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <STDIO.H>
- #include <nds.h>
- #include "font.h"
- /*===========================
- runtime-filled structures
- ============================*/
- typedef struct tagBitmapCanvas
- {
- u16 vx, vy; // vram upload area
- u16 sx, sy; // screen rendering area
- u16 w, h; // pixel size, usually corresponds to 256x224 areas
- u16 row_w; // size of each bitmap row expressed in DWORDs (width/8)
- u16 clut;
- u32 update:1; // set to TRUE if upload is necessary
- u32 pad:31;
- u32* bitmap; // canvas used for rendering
- } BMP_CANVAS;
- typedef struct tagFontData
- {
- u8 w, h; // pixel size, w must be a multiple of 8
- s16 base; // lowest value the font can address
- s16 count; // how many characters are in the font
- s16 replace; // replace out-of-range chars with this value
- u8 *width; // width table
- u8 *data; // font file data
- u16 *fptr; // glyph pointers
- } FONT_DATA;
- typedef struct tagGlyphData
- {
- u16 *fptr; // pointer to the glyph data
- int w; // glyph total width
- } GLYPH_DATA;
- // file format structures and defines
- #define FONT_MAGIC (('P')|('F'<<8)|('N'<<16)|('T'<<24))
- typedef struct tagFontHeader
- {
- u32 magic; // always "PFNT"
- s16 base;
- s16 count;
- s16 replace; // replace out-of-range chars with this value
- u8 w, h;
- } FONT_HEADER;
- typedef struct tagFontGlyph
- {
- u8 w, h;
- } FONT_GLYPH;
- #define WRAPMIN(x,y) if(x<(y)) x=(y);
- #define WRAPMAX(x,y) if(x>(y)) x=(y);
- #define PALMAX 7 // for 2 color fonts '7' is ok
- #define T_WIDTH 8 // segmented tile width
- #define T_HEIGHT 16 // max segment height
- void CreateCanvas(BMP_CANVAS* canvas, int w, int h)
- {
- canvas->row_w=w/8;
- canvas->w=w;
- canvas->h=h;
- canvas->update=FALSE;
- }
- void OpenFont(u8* data, FONT_DATA *dest)
- {
- FONT_HEADER *h=(FONT_HEADER*)data;
- if(h->magic!=FONT_MAGIC)
- {
- //_tprintf("Cannot open font %x %x",h->magic,FONT_MAGIC);
- return;
- }
- dest->data=data;
- dest->width=&data[sizeof(*h)];
- dest->fptr=(u16*)&dest->width[h->count];
- dest->w=h->w;
- dest->h=h->h;
- dest->base=h->base; // change to variable later
- dest->count=h->count;
- dest->replace=h->replace;
- }
- void CanvasDrawMessage(BMP_CANVAS* canvas, FONT_DATA *font, int x, int y, u8* str)
- {
- int i, color;
- int bx=x;
- for(i=0, color=0; str[i]!='\0'; i++)
- {
- if(str[i]=='\n') {y+=font->h; x=bx; continue;}
- if(str[i]==0x01) {color=str[i+1]; i++; continue;}
- x+=DrawCharToCanvas(canvas,font,str[i],x,y,color);
- }
- }
- /*======================================================================
- Impress font character into a bitmap canvas at coordinates specified
- by x and y, with color being the pixel to use for font bit==01.
- =======================================================================
- Return value: character width
- =======================================================================*/
- int DrawCharToCanvas(BMP_CANVAS* canvas, FONT_DATA* font, int ch, int x, int y, int color)
- {
- int w, tw, h;
- GLYPH_DATA glyph;
- u32 conv[T_HEIGHT];
- u16 *fptr;
- // prevent dangerous values for color
- WRAPMIN(color,0);
- WRAPMAX(color,PALMAX);
- // set glyph data
- GetGlyphData(&glyph,font,ch);
- // copy to locals
- w=glyph.w;
- fptr=glyph.fptr;
- h=font->h;
- // do all the rendering
- for(; w>0; w-=T_WIDTH)
- {
- // convert a tile segment
- UpscaleTile(fptr,conv,color,h);
- // seek to next tile segment
- fptr+=h;
- // determine processed width
- tw=(w>=T_WIDTH ? T_WIDTH : w);
- // draw to canvas
- RenderCanvasChar(canvas,conv,x,y,tw,h);
- // move forward with the rendering
- x+=tw;
- }
- // make sure to upload
- canvas->update=TRUE;
- // return the current width
- return glyph.w;
- }
- /*======================================================================
- Clear part of the canvas specified by coordinates and size.
- =======================================================================*/
- void ClearCanvas(BMP_CANVAS* canvas, int x, int y, int w, int h)
- {
- //char message[256];
- int xi, yi, lrest, rrest, row_width;
- u32 *ccanvas, *tcanvas;
- u32 lmask, rmask;
- // fast reference
- ccanvas=canvas->bitmap;
- row_width=canvas->row_w;
- // set tile rest
- lrest=x%T_WIDTH;
- rrest=((x+w)%T_WIDTH);
- // seek canvas to x and y
- ccanvas+=x/T_WIDTH;
- ccanvas+=y*row_width;
- // build masks
- lmask=(0xFFFFFFFF<<lrest*4)^0xFFFFFFFF;
- rmask=(0xFFFFFFFF>>(T_WIDTH-rrest)*4)^0xFFFFFFFF;
- // fix width value
- w-=((T_WIDTH-lrest)+rrest);
- //sprintf(message,"Mask %.8X %.8X width=%d (l=%d r=%d), x=%d y=%d\n",lmask,rmask,w,lrest,rrest,x,y);
- //_tprintf(message);
- // clear lines now
- for(yi=0; yi<h; yi++)
- {
- // get temp line pointer
- tcanvas=ccanvas;
- // mask left edge
- if(lrest>0) {*tcanvas&=lmask; tcanvas++;}
- // delete the aligned area
- for(xi=0; xi<w; xi+=T_WIDTH, tcanvas++) *tcanvas=0;
- // mask right edge
- if(rrest>0) *tcanvas&=rmask;
- // more to next line
- ccanvas+=row_width;
- }
- canvas->update=TRUE;
- }
- #define T_SIZE (T_WIDTH)
- /*======================================================================
- Does all the actual pixel impression. Processes 8x? segments.
- =======================================================================*/
- void RenderCanvasChar(BMP_CANVAS* canvas, u32 *conv, int x, int y, int ch_width, int ch_height)
- {
- int i, trest, row_width, j;
- u32 shift, *ccanvas, *tcanvas;
- // fast reference
- ccanvas=canvas->bitmap;
- row_width=canvas->row_w;
- // set tile rest
- trest=x%T_WIDTH;
- // seek canvas to x and y
- ccanvas+=(x/T_WIDTH)*T_SIZE;
- ccanvas+=(y/T_WIDTH*0x100)+(y%T_WIDTH);
- // next 4 pixels in the canvas
- tcanvas=ccanvas+T_SIZE/*ccanvas+1*/;
- shift=trest*4;
- for(i=0, j=y%T_WIDTH; i<ch_height; i++, j++)
- {
- if(j>=T_WIDTH) {ccanvas+=0x100-T_SIZE; j=0;}
- // shift new tile to the right and include into the old buffer
- *ccanvas|=conv[i]<<shift;
- ccanvas++;
- }
- trest+=ch_width; // trest+ 1~8
- if(trest>T_WIDTH)
- {
- trest-=T_WIDTH;
- shift=(ch_width-trest)*4;
- // move pixels to the right
- for(i=0, j=y%T_WIDTH; i<ch_height; i++, j++)
- {
- if(j>=T_WIDTH) {tcanvas+=0x100-T_SIZE; j=0;}
- *tcanvas|=conv[i]>>shift;
- tcanvas++;
- }
- }
- }
- /*======================================================================
- Set the glyph data from the character index.
- =======================================================================
- NOTE: if char is out of range it is changed to the "unknown" symbol.
- =======================================================================*/
- void GetGlyphData(GLYPH_DATA *glyph, FONT_DATA *font, int ch)
- {
- // check encoding boundaries
- if(ch<font->base && ch>(font->base+font->count)) ch=font->replace; // change to variable
- // obtain font basic value
- else ch-=font->base;
- // obtain width and glyph pointer
- glyph->w=font->width[ch];
- glyph->fptr=(u16*)(font->data+font->fptr[ch]);
- //_tprintf("Reading font data ptr %x, width %d\n",glyph->fptr,glyph->w);
- }
- /*======================================================================
- Upscale variable 2bpp tile to 4 bits
- =======================================================================*/
- void UpscaleTile(u16 *glyph, u32 *dest, int color, int h)
- {
- u32 pline, dline, shift;
- int x, y;
- shift=(u32)(color+1)<<29; // transformation value for each row
- for(y=0; y<h; y++, dest++, glyph++)
- {
- pline=*glyph; // read a line from the font
- dline=0; // clear destination line
- for(x=0; x<T_WIDTH; x++, pline>>=2)
- {
- dline>>=4;
- switch(pline&0x3)
- {
- case 1: dline|=shift|(0<<28); break;
- case 2: dline|=shift|(1<<28); break;
- //case 3: dline|=shift+(2<<28); break;
- }
- }
- // flush line to buffer
- *dest=dline;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement