Advertisement
Guest User

Untitled

a guest
Jul 5th, 2015
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.54 KB | None | 0 0
  1. #include <STDIO.H>
  2. #include <nds.h>
  3. #include "font.h"
  4.  
  5. /*===========================
  6.  runtime-filled structures
  7.  ============================*/
  8. typedef struct tagBitmapCanvas
  9. {
  10.     u16 vx, vy;     // vram upload area
  11.     u16 sx, sy;     // screen rendering area
  12.     u16 w, h;       // pixel size, usually corresponds to 256x224 areas
  13.     u16 row_w;      // size of each bitmap row expressed in DWORDs (width/8)
  14.     u16 clut;
  15.     u32 update:1;   // set to TRUE if upload is necessary
  16.     u32 pad:31;
  17.     u32* bitmap;    // canvas used for rendering
  18. } BMP_CANVAS;
  19.  
  20. typedef struct tagFontData
  21. {
  22.     u8 w, h;        // pixel size, w must be a multiple of 8
  23.     s16 base;       // lowest value the font can address
  24.     s16 count;      // how many characters are in the font
  25.     s16 replace;    // replace out-of-range chars with this value
  26.     u8 *width;      // width table
  27.     u8 *data;       // font file data
  28.     u16 *fptr;      // glyph pointers
  29. } FONT_DATA;
  30.  
  31. typedef struct tagGlyphData
  32. {
  33.     u16 *fptr;      // pointer to the glyph data
  34.     int w;          // glyph total width
  35. } GLYPH_DATA;
  36.  
  37. // file format structures and defines
  38. #define FONT_MAGIC  (('P')|('F'<<8)|('N'<<16)|('T'<<24))
  39.  
  40. typedef struct tagFontHeader
  41. {
  42.     u32 magic;      // always "PFNT"
  43.     s16 base;
  44.     s16 count;
  45.     s16 replace;    // replace out-of-range chars with this value
  46.     u8 w, h;
  47. } FONT_HEADER;
  48.  
  49. typedef struct tagFontGlyph
  50. {
  51.     u8 w, h;
  52. } FONT_GLYPH;
  53.  
  54. #define WRAPMIN(x,y)    if(x<(y)) x=(y);
  55. #define WRAPMAX(x,y)    if(x>(y)) x=(y);
  56.  
  57. #define PALMAX          7   // for 2 color fonts '7' is ok
  58. #define T_WIDTH         8   // segmented tile width
  59. #define T_HEIGHT        16  // max segment height
  60.  
  61. void CreateCanvas(BMP_CANVAS* canvas, int w, int h)
  62. {
  63.     canvas->row_w=w/8;
  64.     canvas->w=w;
  65.     canvas->h=h;
  66.     canvas->update=FALSE;
  67. }
  68.  
  69. void OpenFont(u8* data, FONT_DATA *dest)
  70. {
  71.     FONT_HEADER *h=(FONT_HEADER*)data;
  72.  
  73.     if(h->magic!=FONT_MAGIC)
  74.     {
  75.         //_tprintf("Cannot open font %x %x",h->magic,FONT_MAGIC);
  76.         return;
  77.     }
  78.  
  79.     dest->data=data;
  80.     dest->width=&data[sizeof(*h)];
  81.     dest->fptr=(u16*)&dest->width[h->count];
  82.     dest->w=h->w;
  83.     dest->h=h->h;
  84.     dest->base=h->base; // change to variable later
  85.     dest->count=h->count;
  86.     dest->replace=h->replace;
  87. }
  88.  
  89. void CanvasDrawMessage(BMP_CANVAS* canvas, FONT_DATA *font, int x, int y, u8* str)
  90. {
  91.     int i, color;
  92.     int bx=x;
  93.  
  94.     for(i=0, color=0; str[i]!='\0'; i++)
  95.     {
  96.         if(str[i]=='\n') {y+=font->h; x=bx; continue;}
  97.         if(str[i]==0x01) {color=str[i+1]; i++; continue;}
  98.  
  99.         x+=DrawCharToCanvas(canvas,font,str[i],x,y,color);
  100.     }
  101. }
  102.  
  103. /*======================================================================
  104.  Impress font character into a bitmap canvas at coordinates specified
  105.  by x and y, with color being the pixel to use for font bit==01.
  106.  =======================================================================
  107.  Return value: character width
  108.  =======================================================================*/
  109. int DrawCharToCanvas(BMP_CANVAS* canvas, FONT_DATA* font, int ch, int x, int y, int color)
  110. {
  111.     int w, tw, h;
  112.     GLYPH_DATA glyph;
  113.     u32 conv[T_HEIGHT];
  114.     u16 *fptr;
  115.  
  116.     // prevent dangerous values for color
  117.     WRAPMIN(color,0);
  118.     WRAPMAX(color,PALMAX);
  119.     // set glyph data
  120.     GetGlyphData(&glyph,font,ch);
  121.     // copy to locals
  122.     w=glyph.w;
  123.     fptr=glyph.fptr;
  124.     h=font->h;
  125.  
  126.     // do all the rendering
  127.     for(; w>0; w-=T_WIDTH)
  128.     {
  129.         // convert a tile segment
  130.         UpscaleTile(fptr,conv,color,h);
  131.         // seek to next tile segment
  132.         fptr+=h;
  133.         // determine processed width
  134.         tw=(w>=T_WIDTH ? T_WIDTH : w);
  135.         // draw to canvas
  136.         RenderCanvasChar(canvas,conv,x,y,tw,h);
  137.         // move forward with the rendering
  138.         x+=tw;
  139.     }
  140.  
  141.     // make sure to upload
  142.     canvas->update=TRUE;
  143.  
  144.     // return the current width
  145.     return glyph.w;
  146. }
  147.  
  148. /*======================================================================
  149.  Clear part of the canvas specified by coordinates and size.
  150.  =======================================================================*/
  151. void ClearCanvas(BMP_CANVAS* canvas, int x, int y, int w, int h)
  152. {
  153.     //char message[256];
  154.     int xi, yi, lrest, rrest, row_width;
  155.     u32 *ccanvas, *tcanvas;
  156.     u32 lmask, rmask;
  157.  
  158.     // fast reference
  159.     ccanvas=canvas->bitmap;
  160.     row_width=canvas->row_w;
  161.     // set tile rest
  162.     lrest=x%T_WIDTH;
  163.     rrest=((x+w)%T_WIDTH);
  164.     // seek canvas to x and y
  165.     ccanvas+=x/T_WIDTH;
  166.     ccanvas+=y*row_width;
  167.  
  168.     // build masks
  169.     lmask=(0xFFFFFFFF<<lrest*4)^0xFFFFFFFF;
  170.     rmask=(0xFFFFFFFF>>(T_WIDTH-rrest)*4)^0xFFFFFFFF;
  171.     // fix width value
  172.     w-=((T_WIDTH-lrest)+rrest);
  173.  
  174.     //sprintf(message,"Mask %.8X %.8X width=%d (l=%d r=%d), x=%d y=%d\n",lmask,rmask,w,lrest,rrest,x,y);
  175.     //_tprintf(message);
  176.  
  177.     // clear lines now
  178.     for(yi=0; yi<h; yi++)
  179.     {
  180.         // get temp line pointer
  181.         tcanvas=ccanvas;
  182.  
  183.         // mask left edge
  184.         if(lrest>0) {*tcanvas&=lmask; tcanvas++;}
  185.         // delete the aligned area
  186.         for(xi=0; xi<w; xi+=T_WIDTH, tcanvas++) *tcanvas=0;
  187.         // mask right edge
  188.         if(rrest>0) *tcanvas&=rmask;
  189.  
  190.         // more to next line
  191.         ccanvas+=row_width;
  192.     }
  193.  
  194.     canvas->update=TRUE;
  195. }
  196.  
  197. #define T_SIZE      (T_WIDTH)
  198.  
  199. /*======================================================================
  200.  Does all the actual pixel impression. Processes 8x? segments.
  201.  =======================================================================*/
  202. void RenderCanvasChar(BMP_CANVAS* canvas, u32 *conv, int x, int y, int ch_width, int ch_height)
  203. {
  204.     int i, trest, row_width, j;
  205.     u32 shift, *ccanvas, *tcanvas;
  206.  
  207.     // fast reference
  208.     ccanvas=canvas->bitmap;
  209.     row_width=canvas->row_w;
  210.     // set tile rest
  211.     trest=x%T_WIDTH;
  212.     // seek canvas to x and y
  213.     ccanvas+=(x/T_WIDTH)*T_SIZE;
  214.     ccanvas+=(y/T_WIDTH*0x100)+(y%T_WIDTH);
  215.     // next 4 pixels in the canvas
  216.     tcanvas=ccanvas+T_SIZE/*ccanvas+1*/;
  217.    
  218.     shift=trest*4;
  219.     for(i=0, j=y%T_WIDTH; i<ch_height; i++, j++)
  220.     {
  221.         if(j>=T_WIDTH) {ccanvas+=0x100-T_SIZE; j=0;}
  222.         // shift new tile to the right and include into the old buffer
  223.         *ccanvas|=conv[i]<<shift;
  224.         ccanvas++;
  225.     }
  226.  
  227.     trest+=ch_width;    // trest+ 1~8
  228.     if(trest>T_WIDTH)
  229.     {
  230.         trest-=T_WIDTH;
  231.         shift=(ch_width-trest)*4;
  232.         // move pixels to the right
  233.         for(i=0, j=y%T_WIDTH; i<ch_height; i++, j++)
  234.         {
  235.             if(j>=T_WIDTH) {tcanvas+=0x100-T_SIZE; j=0;}
  236.             *tcanvas|=conv[i]>>shift;
  237.             tcanvas++;
  238.         }
  239.     }
  240. }
  241.  
  242. /*======================================================================
  243.  Set the glyph data from the character index.
  244.  =======================================================================
  245.  NOTE: if char is out of range it is changed to the "unknown" symbol.
  246.  =======================================================================*/
  247. void GetGlyphData(GLYPH_DATA *glyph, FONT_DATA *font, int ch)
  248. {
  249.     // check encoding boundaries
  250.     if(ch<font->base && ch>(font->base+font->count)) ch=font->replace;  // change to variable
  251.     // obtain font basic value
  252.     else ch-=font->base;
  253.     // obtain width and glyph pointer
  254.     glyph->w=font->width[ch];
  255.     glyph->fptr=(u16*)(font->data+font->fptr[ch]);
  256.  
  257.     //_tprintf("Reading font data ptr %x, width %d\n",glyph->fptr,glyph->w);
  258. }
  259.  
  260. /*======================================================================
  261.  Upscale variable 2bpp tile to 4 bits
  262.  =======================================================================*/
  263. void UpscaleTile(u16 *glyph, u32 *dest, int color, int h)
  264. {
  265.     u32 pline, dline, shift;
  266.     int x, y;
  267.    
  268.     shift=(u32)(color+1)<<29;   // transformation value for each row
  269.     for(y=0; y<h; y++, dest++, glyph++)
  270.     {
  271.         pline=*glyph;       // read a line from the font
  272.         dline=0;            // clear destination line
  273.         for(x=0; x<T_WIDTH; x++, pline>>=2)
  274.         {
  275.             dline>>=4;
  276.             switch(pline&0x3)
  277.             {
  278.             case 1: dline|=shift|(0<<28); break;
  279.             case 2: dline|=shift|(1<<28); break;
  280.             //case 3: dline|=shift+(2<<28); break;
  281.             }
  282.         }
  283.         // flush line to buffer
  284.         *dest=dline;
  285.     }
  286. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement