SDL_Surface *btext_render(bfont *f, const char *text, Uint32 bgval, Uint32 fgval, SDL_Rect *rect, Uint32 flags) { Uint32 length, width; Uint32 c, x, y; Uint32 start, lstart, blitoffset; Uint32 dataoffset; unsigned char *utext; SDL_Surface *surface; if(rect == NULL) { length = strlen(text); width = btext_calcWidth(f, text); } else { length = btext_clipTextToWidth(f, text, rect->w, 1); width = rect->w; } if(length == 0) return(NULL); surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, f->height, 32, RMASK, GMASK, BMASK, AMASK); if(surface == NULL) return(NULL); if(SDL_LockSurface(surface) < 0) return(NULL); utext = (unsigned char *)text; start = 0; for(c = 0; c < length; c++) { lstart = start; dataoffset = 0; if(utext[c] >= ' ' && utext[c] <= '\x7f') { for(y = 0; y < f->height; y++) { blitoffset = lstart; for(x = 0; x < (f->widths)[utext[c] - 32]; x++) { if((f->fontData)[utext[c] - 32][dataoffset] == 0) { if(!(flags & BTEXT_BGTRANSPARENT)) PIXELS(surface)[blitoffset] = bgval; } else { if(!(flags & BTEXT_FGTRANSPARENT)) PIXELS(surface)[blitoffset] = fgval; } blitoffset++; dataoffset++; } lstart += surface->w; } start += (f->widths)[text[c] - 32]; } } SDL_UnlockSurface(surface); return(surface); }
GLYPH* font_getglyph(FONT *f, uint32_t ch) { uint32_t hash = ch % 128; GLYPH *g = f->glyphs[hash], *s = g; if(g) { while(g->ucs4 != ~0) { if(g->ucs4 == ch) { return g; } g++; } uint32_t count = (uint32_t)(g - s); g = realloc(s, (count + 2) * sizeof(GLYPH)); if(!g) { return NULL; } f->glyphs[hash] = g; g += count; } else { g = malloc(sizeof(GLYPH) * 2); if(!g) { return NULL; } f->glyphs[hash] = g; } g[1].ucs4 = ~0; FT_UInt index = FT_Get_Char_Index(f->face, ch); FT_Load_Glyph(f->face, index, FT_LOAD_RENDER); FT_GlyphSlotRec *p = f->face->glyph; g->ucs4 = ch; g->x = p->bitmap_left; g->y = PIXELS(f->face->size->metrics.ascender) - p->bitmap_top; g->width = p->bitmap.width; g->height = p->bitmap.rows; g->xadvance = (p->advance.x + (1 << 5)) >> 6; if(f->x + g->width > 512) { f->x = 0; f->y = f->my; } g->mx = f->x; g->my = f->y; glBindTexture(GL_TEXTURE_2D, f->texture); glTexSubImage2D(GL_TEXTURE_2D, 0, f->x, f->y, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, p->bitmap.buffer); f->x += g->width; if(f->y + g->height > f->my) { f->my = f->y + g->height; } return g; }
int btext_renderToSurface(bfont *f, const char *text, Uint32 bgval, Uint32 fgval, SDL_Surface *surface, SDL_Rect *rect, Uint32 flags) { Uint32 length; Uint32 c, x, y; Uint32 start, lstart, blitoffset; Uint32 dataoffset; unsigned char *utext; if(rect->w == 0 || rect->w > surface->w - rect->x) rect->w = surface->w - rect->x; /* clip to surface dimensions */ length = btext_clipTextToWidth(f, text, rect->w, 1); if(length == 0) return(-1); if(SDL_LockSurface(surface) < 0) return(-1); utext = (unsigned char *)text; start = (rect->y * surface->w) + rect->x; for(c = 0; c < length; c++) { lstart = start; dataoffset = 0; if(utext[c] >= ' ' && utext[c] <= '\x7f') { for(y = 0; y < f->height; y++) { blitoffset = lstart; for(x = 0; x < (f->widths)[utext[c] - 32]; x++) { if((f->fontData)[utext[c] - 32][dataoffset] == 0) { if(!(flags & BTEXT_BGTRANSPARENT)) PIXELS(surface)[blitoffset] = bgval; } else { if(!(flags & BTEXT_FGTRANSPARENT)) PIXELS(surface)[blitoffset] = fgval; } blitoffset++; dataoffset++; } lstart += surface->w; } start += (f->widths)[text[c] - 32]; } } SDL_UnlockSurface(surface); return(0); }
bfont *btext_loadFromSurface(SDL_Surface *fontsurface) { bfont *f; Uint32 black; Uint32 x, y, c; Uint8 *data; Uint32 offsets[96]; Uint32 pix, lstart, cpix; SDL_Surface *surface, *surface32; if(fontsurface->h < 2) return(NULL); /* convert surface to 32 bit for easier operation */ surface32 = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, RMASK, GMASK, BMASK, AMASK); if(surface32 == NULL) return(NULL); surface = SDL_ConvertSurface(fontsurface, surface32->format, SDL_SWSURFACE); SDL_FreeSurface(surface32); if(surface == NULL) return(NULL); f = malloc(sizeof(bfont)); if(f == NULL) { SDL_FreeSurface(surface); return(NULL); } f->height = surface->h - 1; black = SDL_MapRGB(surface->format, 0, 0, 0); if(SDL_LockSurface(surface) < 0) { free(f); SDL_FreeSurface(surface); return(NULL); } /* ----- Find Widths ----- */ for(c = 0; c < 96; c++) (f->widths)[c] = 1; c = 0; offsets[0] = 0; for(x = 0; (int)x < surface->w; x++) { if(PIXELS(surface)[x] == black) ((f->widths)[c])++; else { c++; if(c == 96) break; offsets[c] = offsets[c - 1] + (f->widths)[c - 1]; } } if(c != 96) { free(f); return(NULL); } data = malloc(sizeof(Uint8) * (x + 1) * f->height); if(data == NULL) { free(f); return(NULL); } /* ----- Convert data ----- * Format: * fontdata[character][pixel data offset] * Pixel data is stored starting at each char's top left corner and goes to the right for width, then down for height * Pixel value is 0 for background and 1 for foreground */ for(c = 0; c < 96; c++) { lstart = pix = surface->w + offsets[c]; /* skip top line and set pointer to top left pixel of char and set line start pointer */ cpix = 0; /* set font data pointer to start */ (f->fontData)[c] = &(data[offsets[c] * f->height]); /* allocate memory for glyph */ for(y = 0; y < f->height; y++) { for(x = 0; x < (f->widths)[c]; x++) { if(PIXELS(surface)[pix] == black) { (f->fontData)[c][cpix] = 0; cpix++; } else { (f->fontData)[c][cpix] = 1; cpix++; } pix++; /* next pixel */ } lstart = pix = lstart + surface->w; /* next line and update line start pointer */ } } SDL_UnlockSurface(surface); SDL_FreeSurface(surface); return(f); }