Beispiel #1
0
static const char *loadFontFromMemory(
  Font *self, const void *data, int len, int ptsize
) {
  self->font = ttf_new(data, len);
  if (!self->font) {
    return "could not load font";
  }
  ttf_ptsize(self->font, ptsize);
  return NULL;
}
Beispiel #2
0
void ttftest_write(const char *text, const char *font, const char *file, const char *bg, const char *color)
{
  struct image   *ttftext;
  struct image   *gradient;
  struct ttf     *ttf;
  struct color    fg;
  struct rect     drect;
  struct rect     srect;
  
  log(ttftest_log, L_status, "---------- TrueType GIF renderer ----------", text);
  log(ttftest_log, L_status, "text:  %s", text);
  log(ttftest_log, L_status, "font:  %s", font);
  log(ttftest_log, L_status, "bg:    %s", bg);
  log(ttftest_log, L_status, "file:  %s", file);
  log(ttftest_log, L_status, "color: %s", color);
  log(ttftest_log, L_status, "-------------------------------------------");
  
  ttf = ttf_new(font);
  
  if(ttf_open(ttf, font))
  {
    log(ttftest_log, L_fatal, "Could not load font: %s", font);
    return;
  }

  ttf_calc(ttf, 11);
  
  ttf->style |= TTF_STYLE_BOLD;
  
  image_color_parse(&fg, color);
    
  ttftext = ttf_text_blended(ttf, text, &fg);
  
  gradient = image_load_gif(bg);
  
  if(gradient == NULL)
  {
    log(ttftest_log, L_fatal, "Could not load background image: %s", bg);
    return;
  }  
  
  image_convert(gradient, IMAGE_TYPE_32);

  srect = ttftext->rect;

  drect = gradient->rect;
  drect.y = 1;
  drect.x = 6;
  
  image_blit_32to32(ttftext, &srect, gradient, &drect);
  
  image_convert(gradient, IMAGE_TYPE_8);
  
  if(gradient == NULL)
  {
    log(ttftest_log, L_warning, "Could not render test glyph.");
  }
  else
  {
    if(image_save_gif(gradient, file))
    {
      log(ttftest_log, L_fatal, "Could not save output: %s", file);
    }  
  
    image_delete(gradient);
  }
}
Beispiel #3
0
font *
ttf_write_tga (char *name, int32_t pointsize)
{
    uint32_t rmask, gmask, bmask, amask;
    double glyph_per_row;
    char filename[200];
    SDL_Surface *dst;
    uint32_t height;
    uint32_t width;
    double maxx;
    double maxy[TTF_GLYPH_MAX];
    uint32_t c;
    int x;
    int y;
    double h;
    font *f;

    snprintf(filename, sizeof(filename), "%s_pointsize%u.tga",
             name, pointsize);

    if (tex_find(filename)) {
        return (0);
    }

    /*
     * x glyphs horizontally and y vertically.
     */
    glyph_per_row = 16;

    f = ttf_new(name, pointsize, TTF_STYLE_NORMAL);
    if (!f) {
        ERR("could not create font %s", name);
    }

    maxx = 0;
    memset(maxy, 0, sizeof(maxy));

    /*
     * Find the largest font glyph pointsize.
     */
    x = 0;
    y = 0;
    height = 0;

    for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) {

        if (f->tex[c].image) {
            maxx = max(maxx, f->tex[c].image->w);
            maxy[y] = max(maxy[y], f->tex[c].image->h);
        }

        if (++x >= glyph_per_row) {
            x = 0;
            height += maxy[y];
            y++;
        }
    }

    if (!maxx) {
        ERR("no glyphs in font %s", name);
    }

    width = glyph_per_row * maxx;

    if (MULTIPLE_BITS(width)) {
        width = nextpoweroftwo(width);
    }

    height += 40;

    if (MULTIPLE_BITS(height)) {
        height = nextpoweroftwo(height);
    }

    /*
     * Make a large surface for all glyphs.
     */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    rmask = 0xff000000;
    gmask = 0x00ff0000;
    bmask = 0x0000ff00;
    amask = 0x000000ff;
#else
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
#endif

    dst = SDL_CreateRGBSurface(0, width, height, 32,
                               rmask, gmask, bmask, amask);
    if (!dst) {
        ERR("no surface created for size %dx%d font %s", width, height, name);
    }

    newptr(dst, "SDL_CreateRGBSurface");

    /*
     * Blit each glyph to the large surface.
     */
    x = 0;
    y = 0;
    h = 0;

    for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) {

        if (f->tex[c].image) {
            SDL_Rect dstrect = { maxx * x, h, maxx, maxy[y] };

            SDL_BlitSurface(f->tex[c].image, 0, dst, &dstrect);
        }

        if (++x >= glyph_per_row) {
            x = 0;
            h += maxy[y];
            y++;
        }
    }

    /*
     * Convert the black border smoothing that ttf adds into alpha.
     */
    {
        double x;
        double y;

        for (x = 0; x < dst->w; x++) {
            for (y = 0; y < dst->h; y++) {

                color c;

                c = getPixel(dst, x, y);

                if ((c.a == 255) &&
                    (c.r == 255) &&
                    (c.g == 255) &&
                    (c.b == 255)) {
                    /*
                     * Do nothing.
                     */
                } else if ((c.a == 0) &&
                    (c.r == 0) &&
                    (c.g == 0) &&
                    (c.b == 0)) {
                    /*
                     * Do nothing.
                     */
                } else {
                    /*
                     * Convery gray to white with alpha.
                     */
                    c.a = (c.r + c.g + c.b) / 3;
                    c.r = 255;
                    c.g = 255;
                    c.b = 255;
                }

                putPixel(dst, x, y, c);
            }
        }
    }

#define MAX_TEXTURE_HEIGHT 4096

    if (dst->h > MAX_TEXTURE_HEIGHT) {
        ERR("ttf is too large");
    }

    uint8_t filled_pixel_row[MAX_TEXTURE_HEIGHT] = {0};

    /*
     * What the hell am I doing here? The ttf library returns incorrect
     * boounds for the top and bottom of glyphs, so I'm looking for a line of
     * no pixels above and below each glyph so I can really find the texture
     * bounds of a glyph. This allows squeezing of text together.
     */
    {
        int x;
        int y;

        for (y = 0; y < dst->h; y++) {
            for (x = 0; x < dst->w; x++) {
                color c;
                c = getPixel(dst, x, y);
                if (c.r || c.g || c.b || c.a) {
                    filled_pixel_row[y] = true;
                    break;
                }
            }
        }
    }

    /*
     * Work our the tex co-ords for each glyph in the large tex.
     */
    x = 0;
    y = 0;
    h = 0;

    int d1_max = 0;
    int d2_max = 0;

    for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) {

        {
            int y = (h + (h + f->glyphs[c].height)) / 2;

            int miny = y;
            int maxy = y;

            for (;;) {
                if (!filled_pixel_row[miny]) {
                    break;
                }

                miny--;
                if (miny <= 0) {
                    break;
                }
            }

            for (;;) {
                if (!filled_pixel_row[maxy]) {
                    break;
                }

                maxy++;
                if (maxy >= MAX_TEXTURE_HEIGHT - 1) {
                    break;
                }
            }

            int d1 = y - miny;
            if (d1 > d1_max) {
                d1_max = d1;
            }

            int d2 = maxy - y;
            if (d2 > d2_max) {
                d2_max = d2;
            }
        }

        if (++x >= glyph_per_row) {
            x = 0;
            h += maxy[y];
            y++;
        }
    }

    x = 0;
    y = 0;
    h = 0;

    for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) {

        f->glyphs[c].texMinX =
                        (double)(x * maxx) / (double)dst->w;
        f->glyphs[c].texMaxX =
                        (double)((x * maxx) + f->glyphs[c].width) /
                        (double)dst->w;

        {
            int y = (h + (h + f->glyphs[c].height)) / 2;

            int y1 = y - d1_max;
            int y2 = y + d2_max;

            if (y1 < 0) {
                y1 = 0;
            }

            f->glyphs[c].texMinY =
                            (double)(y1) /
                            (double)dst->h;
            f->glyphs[c].texMaxY =
                            (double)(y2) /
                            (double)dst->h;
        }

        if (++x >= glyph_per_row) {
            x = 0;
            h += maxy[y];
            y++;
        }
    }

    SDL_LockSurface(dst);
    stbi_write_tga(filename, dst->w, dst->h, STBI_rgb_alpha, dst->pixels);
    SDL_UnlockSurface(dst);

    texp tex;
    tex = tex_from_surface(dst, filename, filename);
    if (!tex) {
        ERR("could not convert %s to tex", filename);
    }

    /*
     * Work our the tex co-ords for each glyph in the large tex.
     */
    x = 0;
    y = 0;
    h = 0;

    for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) {

        f->tex[c].image = dst;
        f->tex[c].tex = tex_get_gl_binding(tex);
    }

    /*
     * Save the glyph data.
     */
    snprintf(filename, sizeof(filename), "%s_pointsize%u.data",
             name, pointsize);

    FILE *out = fopen(filename, "w");

    fwrite(f->glyphs, sizeof(f->glyphs), 1, out);

    fclose(out);

    printf("wrote %s\n",filename);
    return (f);
}