r3938 - in trunk/misc: . ttf2conchars
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sun Jul 27 05:22:01 EDT 2008
Author: div0
Date: 2008-07-27 05:21:48 -0400 (Sun, 27 Jul 2008)
New Revision: 3938
Added:
trunk/misc/ttf2conchars/
trunk/misc/ttf2conchars/foo.sh
trunk/misc/ttf2conchars/ttf2conchars.c
Log:
add ttf2conchars (very hard to use)
Added: trunk/misc/ttf2conchars/foo.sh
===================================================================
--- trunk/misc/ttf2conchars/foo.sh (rev 0)
+++ trunk/misc/ttf2conchars/foo.sh 2008-07-27 09:21:48 UTC (rev 3938)
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -ex
+gcc -Wall -Wextra ttf2conchars.c `sdl-config --cflags --libs` -lSDL_ttf -lSDL_image -ggdb3
+#./a.out source.tga /home/rpolzer/.nexuiz/data/gfx/vera-sans.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraSeBd.ttf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBI.ttf 0.05 0.004 0.000000000000001
+#./a.out source.tga 0 56 /home/rpolzer/.nexuiz/data/gfx/vera-sans.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 0.05 0.004 0.000000000000001
+./a.out ~/software/games/nexuiz/data/gfx/conchars.tga 0 56 64 /home/rpolzer/.nexuiz/data/gfx/vera-sans.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 0.05 0.004 0.000000000000001
+#./a.out source.tga /home/rpolzer/.nexuiz/data/gfx/conchars.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraMoBd.ttf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraSeBd.ttf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBI.ttf 0.05 0.004 0.000000000000001
+display /home/rpolzer/.nexuiz/data/gfx/vera-sans.tga
Added: trunk/misc/ttf2conchars/ttf2conchars.c
===================================================================
--- trunk/misc/ttf2conchars/ttf2conchars.c (rev 0)
+++ trunk/misc/ttf2conchars/ttf2conchars.c 2008-07-27 09:21:48 UTC (rev 3938)
@@ -0,0 +1,769 @@
+#include <stdio.h>
+#include <err.h>
+#include <math.h>
+#include "SDL/SDL.h"
+#include "SDL/SDL_ttf.h"
+#include "SDL/SDL_image.h"
+
+void Image_WriteTGABGRA (const char *filename, int width, int height, const unsigned char *data)
+{
+ int y;
+ unsigned char *buffer, *out;
+ const unsigned char *in, *end;
+ FILE *f;
+
+ buffer = (unsigned char *)malloc(width*height*4 + 18);
+
+ memset (buffer, 0, 18);
+ buffer[2] = 2; // uncompressed type
+ buffer[12] = (width >> 0) & 0xFF;
+ buffer[13] = (width >> 8) & 0xFF;
+ buffer[14] = (height >> 0) & 0xFF;
+ buffer[15] = (height >> 8) & 0xFF;
+
+ for (y = 3;y < width*height*4;y += 4)
+ if (data[y] < 255)
+ break;
+
+ if (y < width*height*4)
+ {
+ // save the alpha channel
+ buffer[16] = 32; // pixel size
+ buffer[17] = 8; // 8 bits of alpha
+
+ // flip upside down
+ out = buffer + 18;
+ for (y = height - 1;y >= 0;y--)
+ {
+ memcpy(out, data + y * width * 4, width * 4);
+ out += width*4;
+ }
+ }
+ else
+ {
+ // save only the color channels
+ buffer[16] = 24; // pixel size
+ buffer[17] = 0; // 8 bits of alpha
+
+ // truncate bgra to bgr and flip upside down
+ out = buffer + 18;
+ for (y = height - 1;y >= 0;y--)
+ {
+ in = data + y * width * 4;
+ end = in + width * 4;
+ for (;in < end;in += 4)
+ {
+ *out++ = in[0];
+ *out++ = in[1];
+ *out++ = in[2];
+ }
+ }
+ }
+
+ f = fopen(filename, "wb");
+ if(!f)
+ err(1, "WriteTGA");
+ if(fwrite(buffer, out - buffer, 1, f) != 1)
+ err(1, "WriteTGA");
+ if(fclose(f))
+ err(1, "WriteTGA");
+
+ free(buffer);
+}
+
+/*
+ * Return the pixel value at (x, y)
+ * NOTE: The surface must be locked before calling this!
+ */
+Uint32 getpixel(SDL_Surface *surface, int x, int y)
+{
+ int bpp = surface->format->BytesPerPixel;
+ /* Here p is the address to the pixel we want to retrieve */
+ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
+
+ switch(bpp) {
+ case 1:
+ return *p;
+
+ case 2:
+ return *(Uint16 *)p;
+
+ case 3:
+ if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
+ return p[0] << 16 | p[1] << 8 | p[2];
+ else
+ return p[0] | p[1] << 8 | p[2] << 16;
+
+ case 4:
+ return *(Uint32 *)p;
+
+ default:
+ return 0; /* shouldn't happen, but avoids warnings */
+ }
+}
+
+/*
+ * Set the pixel at (x, y) to the given value
+ * NOTE: The surface must be locked before calling this!
+ */
+void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
+{
+ int bpp = surface->format->BytesPerPixel;
+ /* Here p is the address to the pixel we want to set */
+ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
+
+ switch(bpp) {
+ case 1:
+ *p = pixel;
+ break;
+
+ case 2:
+ *(Uint16 *)p = pixel;
+ break;
+
+ case 3:
+ if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
+ p[0] = (pixel >> 16) & 0xff;
+ p[1] = (pixel >> 8) & 0xff;
+ p[2] = pixel & 0xff;
+ } else {
+ p[0] = pixel & 0xff;
+ p[1] = (pixel >> 8) & 0xff;
+ p[2] = (pixel >> 16) & 0xff;
+ }
+ break;
+
+ case 4:
+ *(Uint32 *)p = pixel;
+ break;
+ }
+}
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define BOUND(a,b,c) MAX(a,MIN(b,c))
+#define BLURFUNC(d,A,B) A-B*(d)
+#define BLURFUNCIMAX(A,B) ceil(sqrt((A)/(B)))
+
+Uint32 getpixelfilter(SDL_Surface *src, SDL_PixelFormat *fmt, int x, int y, double A, double B, double C)
+{
+ double r, g, b, a, f;
+ Uint8 pr, pg, pb, pa;
+ int i, j;
+ int imax = BLURFUNCIMAX(A,B);
+
+ // 1. calculate blackened blurred image
+ a = 0;
+ for(i=-imax; i<=imax; ++i)
+ if(y+i >= 0 && y+i < src->h)
+ for(j=-imax; j<=imax; ++j)
+ if(x+j >= 0 && x+j < src->w)
+ {
+ SDL_GetRGBA(getpixel(src, x+j, y+i), src->format, &pr, &pg, &pb, &pa);
+ f = BLURFUNC(i*i+j*j, A, B);
+ f = MAX(0, f);
+
+ if(C == 0)
+ a = MAX(a, pa * f);
+ else
+ a = a + pa * f;
+ }
+ a = MIN(a, 255);
+
+ if(C == 0)
+ {
+ // 2. overlap it with the actual image again
+ if(y >= 0 && y < src->h && x >= 0 && x < src->w)
+ {
+ SDL_GetRGBA(getpixel(src, x, y), src->format, &pr, &pg, &pb, &pa);
+
+ f = a + pa - (a * pa) / 255L;
+
+ r = pr * pa / f;
+ g = pg * pa / f;
+ b = pb * pa / f;
+
+ a = f;
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0;
+ a = a;
+ }
+ }
+ else if(C > 0)
+ r = g = b = MAX(0, 255 - C * (255 - a));
+ else if(C < 0)
+ r = g = b = MAX(0, 255 + C * a);
+
+ return SDL_MapRGBA(fmt, r, g, b, a);
+}
+
+void blitfilter(SDL_Surface *src, SDL_Surface *dest, int x0, int y0, double A, double B, double C)
+{
+ // note: x0, y0 is the origin of the UNFILTERED image; it is "transparently" expanded by a BLURFUNCIMAX.
+ int x, y, d;
+
+ d = BLURFUNCIMAX(A,B);
+ SDL_LockSurface(src);
+ SDL_LockSurface(dest);
+ for(y = -d; y < d + src->h; ++y)
+ for(x = -d; x < d + src->w; ++x)
+ putpixel(dest, x + x0, y + y0, getpixelfilter(src, dest->format, x, y, A, B, C));
+ SDL_UnlockSurface(dest);
+ SDL_UnlockSurface(src);
+}
+
+int mapFont(int d, char *c_)
+{
+ unsigned char *c = (unsigned char *) c_;
+ if(!d)
+ return (*c >= 0x20 && *c <= 0x7E) || (*c >= 0xA0 && *c <= 0xFE) ? 0 : -1;
+ if(*c >= 0x20 && *c <= 0x7E)
+ return 0;
+ if(*c >= 0xA0 && *c <= 0xAF)
+ {
+ *c &= 0x7F;
+ return 1;
+ }
+ if(*c >= 0xB0 && *c <= 0xB9)
+ {
+ *c &= 0x7F;
+ return 2;
+ }
+ if(*c >= 0xBA && *c <= 0xDF)
+ {
+ *c &= 0x7F;
+ return 1; // cool
+ }
+ if(*c >= 0xE0 && *c <= 0xFE)
+ {
+ *c &= 0x5F;
+ return 2; // lcd
+ }
+ return -1;
+}
+
+/**
+ * @brief Blit a surface onto another and stretch it.
+ * With a 4.2 gcc you can use -fopenmp :)
+ * You might want to add some linear fading for scaling up?
+ *
+ * @param dst Destination surface
+ * @param src Source surface, if NULL, the destination surface is used
+ * @param drec The target area
+ * @param srec The source area, if NULL, then you suck :P
+ */
+void StretchBlit(SDL_Surface *dst, SDL_Surface *src, SDL_Rect *drec, SDL_Rect *srec)
+{
+ if(!src)
+ src = dst;
+
+ unsigned int freeSource = 0;
+ if(src == dst) {
+ // To avoid copying copied pixels, that would suck :)
+ src = SDL_ConvertSurface(dst, dst->format, dst->flags);
+ freeSource = 1;
+ }
+
+ if(!drec)
+ drec = &dst->clip_rect;
+ if(!srec)
+ srec = &src->clip_rect;
+
+ SDL_LockSurface(dst);
+ SDL_LockSurface(src);
+
+ double scaleX = (double)srec->w / (double)drec->w;
+ double scaleY = (double)srec->h / (double)drec->h;
+
+ int x, y;
+
+ for(y = drec->y; y < (drec->y + drec->h); ++y)
+ {
+ if(y >= dst->h)
+ break;
+ int dy = y - drec->y;
+ for(x = drec->x; x < (drec->x + drec->w); ++x)
+ {
+ if(x >= dst->w)
+ break;
+ // dx, dy relative to the drec start
+ int dx = x - drec->x;
+
+ double dfromX, dfromY, dtoX, dtoY;
+ int fromX, fromY, toX, toY;
+ // Get the pixel range which represents the current pixel
+ // When scaling down this should be a rectangle :)
+ // Otherwise it's just 1 pixel anyway, from==to then
+ dfromX = dx * scaleX;
+ dfromY = dy * scaleY;
+ dtoX = (dx+1) * scaleX;
+ dtoY = (dy+1) * scaleY;
+ // The first and last one usually aren't 100% within this space
+ fromX = (int)dfromX; dfromX = 1.0 - (dfromX - fromX); // invert the from percentage
+ fromY = (int)dfromY; dfromY = 1.0 - (dfromY - fromY);
+ toX = (int)dtoX; dtoX -= toX; // this one is ok
+ toY = (int)dtoY; dtoY -= toY;
+
+ /* Short explanation:
+ * FROM is where to START, so when it's 5.7, then 30% of the 5th pixel is to be used
+ * TO is where it ENDS, so if it's 8.4, then 40% of the 9th pixel is to be used!
+ */
+
+ // Now get all the pixels and merge them together...
+ int i, j;
+ unsigned int r, g, b, a, ar, ag, ab;
+ unsigned int count = 0;
+ r = g = b = a = ar = ag = ab = 0;
+ /*if(drec->w > 1024)
+ printf("%i %i - %f %f\n", fromX, toX, dfromX, dtoX);*/
+
+ // when going from one to the next there's usually one
+ // situation where the left pixel has a value of 0.1something and
+ // the right one of 0
+ // so adjust the values here
+ // otherwise we get lines in the image with the original color
+ // of the left pixel
+ if(toX - fromX == 1 && drec->w > srec->w) {
+ dfromX = 1.0 - dtoX;
+ ++fromX;
+ }
+ if(fromX == toX) {
+ dfromX -= 0.5;
+ if(dfromX > 0.0) {
+ --fromX;
+ dtoX = 1.0-dfromX;
+ } else {
+ ++toX;
+ dtoX = -dfromX;
+ dfromX = 1.0-dtoX;
+ }
+ }
+ if(toY - fromY == 1 && drec->h > srec->h) {
+ dfromY = 1.0 - dtoY;
+ ++fromY;
+ }
+ if(fromY == toY) {
+ dfromY -= 0.5;
+ if(dfromY > 0.0) {
+ --fromY;
+ dtoY = 1.0-dfromY;
+ } else {
+ ++toY;
+ dtoY = -dfromY;
+ dfromY = 1.0-dtoY;
+ }
+ }
+ for(j = fromY; j <= toY; ++j)
+ {
+ if(j < 0)
+ continue;
+ if((j+srec->y) >= src->h)
+ break;
+ for(i = fromX; i <= toX; ++i)
+ {
+ Uint8 pr, pg, pb, pa;
+ Uint16 par, pag, pab;
+ double inc = 1;
+ if(x < 0)
+ continue;
+ if((i+srec->x) >= src->w)
+ break;
+
+ SDL_GetRGBA(getpixel(src, i + srec->x, j + srec->y), src->format, &pr, &pg, &pb, &pa);
+ par = pa * (unsigned int)pr;
+ pag = pa * (unsigned int)pg;
+ pab = pa * (unsigned int)pb;
+
+ if(i == fromX)
+ inc *= dfromX;
+ if(j == fromY)
+ inc *= dfromY;
+ if(i == (toX))
+ inc *= dtoX;
+ if(j == (toY))
+ inc *= dtoY;
+
+ int iinc = inc * 256;
+
+ r += (pr * iinc);
+ g += (pg * iinc);
+ b += (pb * iinc);
+ ar += (par * iinc);
+ ag += (pag * iinc);
+ ab += (pab * iinc);
+ a += (pa * iinc);
+ //++count;
+ count += iinc;
+ }
+ }
+ //printf("COLOR VALUE: %i, %i, %i, %i \t COUNT: %f\n", r, g, b, a, count);
+ if(a)
+ {
+ r = ar / a;
+ g = ag / a;
+ b = ab / a;
+ a /= count;
+ }
+ else
+ {
+ r /= count;
+ g /= count;
+ b /= count;
+ a /= count;
+ }
+
+ putpixel(dst, x, y, SDL_MapRGBA(dst->format, (Uint8)r, (Uint8)g, (Uint8)b, (Uint8)a));
+ }
+ }
+
+ SDL_UnlockSurface(dst);
+ SDL_UnlockSurface(src);
+
+ if(freeSource)
+ SDL_FreeSurface(src);
+}
+
+void StretchDown(SDL_Surface *srfc, int x, int y, int w, int h, int wtarget)
+{
+ // @"#$ SDL has no StretchBlit
+ // this one is slow, but at least I know how it works
+ int r, c;
+ unsigned int stretchedline[8 * wtarget]; // ra ga ba r g b a n
+ SDL_LockSurface(srfc);
+
+ for(r = y; r < y + h; ++r)
+ {
+ // each input pixel is wtarget pixels "worth"
+ //memset(stretchedline, sizeof(stretchedline), 0);
+ memset(stretchedline, 0, sizeof(stretchedline));
+ for(c = 0; c < w * wtarget; ++c)
+ {
+ Uint8 pr, pg, pb, pa;
+ unsigned int *p = &stretchedline[8 * (c / w)];
+ SDL_GetRGBA(getpixel(srfc, x + c / wtarget, r), srfc->format, &pr, &pg, &pb, &pa);
+ p[0] += (unsigned int) pr * (unsigned int) pa;
+ p[1] += (unsigned int) pg * (unsigned int) pa;
+ p[2] += (unsigned int) pb * (unsigned int) pa;
+ p[3] += (unsigned int) pr;
+ p[4] += (unsigned int) pg;
+ p[5] += (unsigned int) pb;
+ p[6] += (unsigned int) pa;
+ p[7] += 1;
+ }
+ for(c = 0; c < wtarget; ++c)
+ {
+ unsigned int *p = &stretchedline[8 * c];
+ if(p[6])
+ putpixel(srfc, x + c, r, SDL_MapRGBA(srfc->format, p[0] / p[6], p[1] / p[6], p[2] / p[6], p[6] / p[7]));
+ else
+ putpixel(srfc, x + c, r, SDL_MapRGBA(srfc->format, p[3] / p[7], p[4] / p[7], p[5] / p[7], p[6] / p[7]));
+ }
+ for(c = wtarget; c < w; ++c)
+ putpixel(srfc, x + c, r, SDL_MapRGBA(srfc->format, 0, 0, 0, 0));
+ }
+
+ SDL_UnlockSurface(srfc);
+}
+
+int GetBoundingBox(SDL_Surface *surf, const SDL_Rect *inbox, SDL_Rect *outbox)
+{
+ int bx = -1, by = -1; // start
+ //int bw = 0, bh = 0;
+ int ex = -1, ey = -1; // end
+ int cx, cy;
+ for(cx = inbox->x; cx < inbox->x + inbox->w; ++cx)
+ {
+ for(cy = inbox->y; cy < inbox->y + inbox->h; ++cy)
+ {
+ Uint8 pr, pg, pb, pa;
+ SDL_GetRGBA(getpixel(surf, cx, cy), surf->format, &pr, &pg, &pb, &pa);
+ // include colors, or only care about pa?
+ if(!pa)
+ continue;
+
+ if(bx < 0) {
+ bx = ex = cx;
+ by = ey = cy;
+ continue;
+ }
+
+ if(cx < bx) // a pixel more on the left
+ bx = cx;
+ /*if(cy < by) // a pixel more above... wait... this cannot happen actually
+ by = cy;*/
+ if(cx > ex) // a pixel on the right
+ ex = cx;
+ if(cy > ey) // a pixel on the bottom :)
+ ey = cy;
+ }
+ }
+
+ if(ex < 0)
+ return 0;
+
+ outbox->x = bx;
+ outbox->y = by;
+ outbox->w = (ex - bx + 1);
+ outbox->h = (ey - by + 1);
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ SDL_Rect in, out;
+ SDL_Surface *conchars, *conchars0;
+ SDL_Surface *glyph;
+ TTF_Font *fonts[3];
+ SDL_Color white = {255, 255, 255, 255};
+ Uint32 transparent;
+ int maxAscent, maxDescent, maxWidth;
+ int i;
+ int currentSize;
+ int isfixed;
+
+ if(argc != 12)
+ errx(1, "Usage: %s infile.tga topref bottomref cellheight outfile.tga font.ttf fontCOOL.ttf fontLCD.ttf blurA blurB blurColors\n", argv[0]);
+
+ const char *infilename = argv[1];
+ int referenceTop = atoi(argv[2]);
+ int referenceBottom = atoi(argv[3]);
+ int cell = atoi(argv[4]);
+ const char *outfilename = argv[5];
+ const char *font0 = argv[6];
+ const char *font1 = argv[7];
+ const char *font2 = argv[8];
+ double A = atof(argv[9]);
+ double B = atof(argv[10]);
+ double C = atof(argv[11]);
+ int differentFonts;
+
+ char widthfilename[512];
+ snprintf(widthfilename, sizeof(widthfilename), "%.*s.width", (int)strlen(outfilename) - 4, outfilename);
+
+ int border=BLURFUNCIMAX(A, B);
+
+ fprintf(stderr, "Using %d border pixels\n", border);
+
+ if(SDL_Init(0) < 0)
+ errx(1, "SDL_Init failed");
+
+ if(TTF_Init() < 0)
+ errx(1, "TTF_Init failed: %s", TTF_GetError());
+
+ conchars0 = IMG_Load(infilename);
+ if(!conchars0)
+ errx(1, "IMG_Load failed: %s", IMG_GetError());
+
+ if(conchars0->w != conchars0->h)
+ errx(1, "conchars aren't square");
+ if(conchars0->w % 16)
+ errx(1, "conchars have bad width");
+
+ conchars = SDL_CreateRGBSurface(SDL_SWSURFACE, cell * 16, cell * 16, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
+ in.x = in.y = out.x = out.y = 0;
+ in.w = in.h = conchars0->w;
+ out.w = out.h = cell * 16;
+ StretchBlit(conchars, conchars0, &out, &in);
+ SDL_FreeSurface(conchars0);
+
+ for(currentSize = cell * 2; currentSize; --currentSize)
+ {
+ fonts[0] = TTF_OpenFont(font0, currentSize);
+ if(!fonts[0])
+ errx(1, "TTF_OpenFont failed: %s", TTF_GetError());
+
+ if(strcmp(font0, font1) || strcmp(font0, font2))
+ {
+ fonts[1] = TTF_OpenFont(font1, currentSize);
+ if(!fonts[1])
+ warnx("TTF_OpenFont failed: %s", TTF_GetError());
+
+ fonts[2] = TTF_OpenFont(font2, currentSize);
+ if(!fonts[2])
+ warnx("TTF_OpenFont failed: %s", TTF_GetError());
+
+ differentFonts = 1;
+ }
+ else
+ {
+ fonts[1] = fonts[2] = fonts[0];
+ differentFonts = 0;
+ }
+
+ //maxAscent = MAX(MAX(TTF_FontAscent(fonts[0]), fonts[1] ? TTF_FontAscent(fonts[1]) : 0), fonts[2] ? TTF_FontAscent(fonts[2]) : 0);
+ //maxDescent = -MIN(MIN(TTF_FontDescent(fonts[0]), fonts[1] ? TTF_FontDescent(fonts[1]) : 0), fonts[2] ? TTF_FontDescent(fonts[2]) : 0);
+ maxAscent = 0;
+ maxDescent = 0;
+ maxWidth = 0;
+ for(i = 0; i < 256; ++i)
+ {
+ char str[2]; str[0] = i; str[1] = 0;
+ int fntid = mapFont(differentFonts, &str[0]);
+ if(fntid < 0)
+ continue;
+ if(!fonts[fntid])
+ continue;
+ glyph = TTF_RenderText_Blended(fonts[fntid], str, white);
+ if(!glyph)
+ errx(1, "TTF_RenderText_Blended %d failed: %s", i, TTF_GetError());
+ if(fntid == 0)
+ maxWidth = MAX(maxWidth, glyph->w);
+
+ in.x = 0;
+ in.y = 0;
+ in.w = glyph->w;
+ in.h = glyph->h;
+ if(GetBoundingBox(glyph, &in, &out))
+ {
+ int baseline = TTF_FontAscent(fonts[fntid]);
+ int asc = baseline - out.y;
+ int desc = (out.y + out.h - 1) - baseline;
+ if(asc > maxAscent)
+ maxAscent = asc;
+ if(desc > maxDescent)
+ maxDescent = desc;
+ }
+
+ SDL_FreeSurface(glyph);
+ }
+
+ if(border + maxAscent + 1 + maxDescent + border <= cell)
+ if(border + maxWidth + border <= cell)
+ break; // YEAH
+
+ if(differentFonts)
+ {
+ TTF_CloseFont(fonts[2]);
+ TTF_CloseFont(fonts[1]);
+ }
+ TTF_CloseFont(fonts[0]);
+ }
+ if(!currentSize)
+ errx(1, "Sorry, no suitable size found.");
+ fprintf(stderr, "Using font size %d (%d + 1 + %d)\n", currentSize, maxAscent, maxDescent);
+
+ isfixed = TTF_FontFaceIsFixedWidth(fonts[0]);
+ if(getenv("FORCE_FIXED"))
+ isfixed = 1;
+
+ // TODO convert conchars to BGRA (so the TGA writer can reliably use it)
+
+ transparent = SDL_MapRGBA(conchars->format, 255, 0, 255, 0);
+
+ FILE *widthfile = fopen(widthfilename, "w");
+ if(!widthfile)
+ err(1, "fopen widthfile");
+ fprintf(widthfile, "extraspacing %f ", 0.0);
+
+ for(i = 0; i < 256; ++i)
+ {
+ int w, h;
+ int fntid;
+ SDL_Rect dest;
+ char str[2]; str[0] = i; str[1] = 0;
+
+ if(!(i % 16))
+ fprintf(widthfile, "\n");
+
+ fntid = mapFont(differentFonts, &str[0]);
+ if(fntid < 0 || !fonts[fntid])
+ {
+ SDL_Rect src, src2;
+ src.x = cell * (i % 16);
+ src.y = cell * (i / 16);
+ src.w = cell;
+ src.h = cell;
+ src2.x = 0;
+ src2.y = 0;
+ src2.w = cell;
+ src2.h = cell;
+ glyph = SDL_CreateRGBSurface(SDL_SWSURFACE, cell, cell, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+ SDL_FillRect(glyph, &src2, transparent);
+
+ // map:
+ // referenceTop -> (cell - (maxAscent + 1 + maxDescent)) / 2
+ // referenceBottom -> (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent
+
+ int destTop = (cell - (maxAscent + 1 + maxDescent)) / 2;
+ int destBottom = (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent;
+
+ // map is:
+ // x' = x / cell * h + y
+ // solve:
+ // destTop = referenceTop / cell * h + y
+ // destBottom = referenceBottom / cell * h + y
+
+ dest.x = 0;
+ dest.y = (destBottom * referenceTop - destTop * referenceBottom) / (double) (referenceTop - referenceBottom);
+ dest.w = dest.h;
+ dest.h = cell * (destBottom - destTop) / (double) (referenceBottom - referenceTop);
+
+ /*
+ if(dest.y < 0)
+ dest.y = 0;
+ if(dest.w > glyph->w)
+ dest.w = glyph->w;
+ if(dest.y + dest.h > glyph->h)
+ dest.h = glyph->h - dest.y;
+ */
+
+ if(isfixed)
+ dest.w = border + maxWidth + border;
+ StretchBlit(glyph, conchars, &dest, &src);
+ //SDL_FillRect(conchars, &src, transparent);
+ //SDL_BlitSurface(glyph, &src2, conchars, &src);
+ StretchBlit(conchars, glyph, &src, &src2);
+ SDL_FreeSurface(glyph);
+ fprintf(widthfile, "%f ", dest.w / (double) cell);
+ continue;
+ }
+
+ fprintf(stderr, "glyph %d...\n", i);
+
+ glyph = TTF_RenderText_Blended(fonts[fntid], str, white);
+ if(!glyph)
+ errx(1, "TTF_RenderText_Blended %d failed: %s", i, TTF_GetError());
+
+ w = border + glyph->w + border;
+ h = border + glyph->h + border;
+ if(w > cell)
+ warnx("sorry, this font contains a character that is too wide... output will be borked");
+
+ dest.x = cell * (i % 16);
+ dest.y = cell * (i / 16);
+ dest.w = cell;
+ dest.h = cell;
+ SDL_FillRect(conchars, &dest, transparent);
+
+ dest.x += border + (isfixed ? ((border + maxWidth + border - w) / 2) : 0);
+ dest.y += (cell - (maxAscent + 1 + maxDescent)) / 2 + (maxAscent - TTF_FontAscent(fonts[fntid]));
+ blitfilter(glyph, conchars, dest.x, dest.y, A, B, C);
+
+ SDL_FreeSurface(glyph);
+
+ if(isfixed && w > border + maxWidth + border)
+ {
+ StretchDown(conchars, cell * (i % 16), cell * (i / 16), w, cell, border + maxWidth + border);
+ fprintf(widthfile, "%f ", (border + maxWidth + border) / (double) cell);
+ }
+ else
+ fprintf(widthfile, "%f ", (isfixed ? border + maxWidth + border : w) / (double) cell);
+ }
+
+ fprintf(widthfile, "\n");
+ fclose(widthfile);
+
+ fprintf(stderr, "Writing...\n");
+
+ Image_WriteTGABGRA(outfilename, conchars->w, conchars->h, conchars->pixels);
+
+ SDL_FreeSurface(conchars);
+
+ SDL_Quit();
+
+ return 0;
+}
More information about the nexuiz-commits
mailing list