Example #1
0
static void *font_renderer_stb_init(const char *font_path, float font_size)
{
   int ascent, descent, line_gap;
   stbtt_fontinfo info;
   uint8_t *font_data = NULL;
   stb_font_renderer_t *self = (stb_font_renderer_t*) calloc(1, sizeof(*self));

   /* See https://github.com/nothings/stb/blob/master/stb_truetype.h#L539 */
   font_size = STBTT_POINT_SIZE(font_size);

   if (!self)
      goto error;

   if (!filestream_read_file(font_path, (void**)&font_data, NULL))
      goto error;

   if (!font_renderer_stb_create_atlas(self, font_data, font_size, 512, 512))
      goto error;

   if (!stbtt_InitFont(&info, font_data, stbtt_GetFontOffsetForIndex(font_data, 0)))
      goto error;

   stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap);
   self->line_height  = ascent - descent;

   if (font_size < 0)
      self->line_height *= stbtt_ScaleForMappingEmToPixels(&info, -font_size);
   else
      self->line_height *= stbtt_ScaleForPixelHeight(&info, font_size);

   free(font_data);

   return self;

error:
   if (font_data)
      free(font_data);

   if (self)
      font_renderer_stb_free(self);
   return NULL;
}
Example #2
0
static void *font_renderer_stb_init(const char *font_path, float font_size)
{
   uint8_t *font_data = NULL;
   int ascent, descent, line_gap;
   stbtt_fontinfo info;
   stb_font_renderer_t *self = (stb_font_renderer_t*) calloc(1, sizeof(*self));

   /* prevent warnings */
   (void)rect_width_compare;

   if (!self)
      goto error;

   if (!read_file(font_path, (void**)&font_data, NULL))
      goto error;

   if (!font_renderer_stb_create_atlas(self, font_data, font_size))
      goto error;

   if (!stbtt_InitFont(&info, font_data, stbtt_GetFontOffsetForIndex(font_data, 0)))
      goto error;

   stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap);
   self->line_height  = ascent - descent;// + line_gap;

   if (font_size < 0)
      self->line_height *= stbtt_ScaleForMappingEmToPixels(&info, -font_size);
   else
      self->line_height *= stbtt_ScaleForPixelHeight(&info, font_size);

   free(font_data);

   return self;

error:
   if (font_data)
      free(font_data);

   font_renderer_stb_free(self);
   return NULL;
}
Example #3
0
static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
      uint8_t *font_data, float font_size, unsigned width, unsigned height)
{
   int i;
   stbtt_pack_context pc = {NULL};
   stbtt_packedchar   chardata[256];

   if (width > 2048 || height > 2048)
   {
      RARCH_WARN("[stb] Font atlas too big: %ux%u\n", width, height);
      goto error;
   }

   if (self->atlas.buffer)
      free(self->atlas.buffer);

   self->atlas.buffer = (uint8_t*)calloc(height, width);
   self->atlas.width  = width;
   self->atlas.height = height;

   if (!self->atlas.buffer)
      goto error;

   stbtt_PackBegin(&pc, self->atlas.buffer,
         self->atlas.width, self->atlas.height,
         self->atlas.width, 1, NULL);

   stbtt_PackFontRange(&pc, font_data, 0, font_size, 0, 256, chardata);
   stbtt_PackEnd(&pc);

   for (i = 0; i < 256; ++i)
   {
      struct font_glyph *g = &self->glyphs[i];
      stbtt_packedchar  *c = &chardata[i];

      g->advance_x = c->xadvance;
      g->atlas_offset_x = c->x0;
      g->atlas_offset_y = c->y0;
      g->draw_offset_x  = c->xoff;
      g->draw_offset_y  = c->yoff;
      g->width          = c->x1 - c->x0;
      g->height         = c->y1 - c->y0;

      /* Make sure important characters fit */
      if (isalnum(i) && (!g->width || !g->height))
      {
         int new_width  = width  * 1.2;
         int new_height = height * 1.2;

         /* Limit growth to 2048x2048 unless we already reached that */
         if (width < 2048 || height < 2048)
         {
            new_width  = MIN(new_width,  2048);
            new_height = MIN(new_height, 2048);
         }

         return font_renderer_stb_create_atlas(self, font_data, font_size,
               new_width, new_height);
      }
   }

   return true;

error:
   self->atlas.width = self->atlas.height = 0;

   if (self->atlas.buffer)
      free(self->atlas.buffer);

   self->atlas.buffer = NULL;

   return false;
}