Beispiel #1
0
static const char *initFont(font_t *self, const void *data, int ptsize) {
  int i;

  /* Init font */
  stbtt_fontinfo font;
  if ( !stbtt_InitFont(&font, data, 0) ) {
    return "could not load font";
  }

  /* Get height and scale */
  int ascent, descent, lineGap;
  stbtt_GetFontVMetrics(&font, &ascent, &descent, &lineGap);
  float scale = stbtt_ScaleForMappingEmToPixels(&font, ptsize);
  self->height = (ascent - descent + lineGap) * scale + 0.5;

  /* Init image */
  int w = 128, h = 128;
retry:
  image_initBlank(&self->image, w, h);

  /* Load glyphs */
  float s = stbtt_ScaleForMappingEmToPixels(&font, 1) /
            stbtt_ScaleForPixelHeight(&font, 1);
  int res = stbtt_BakeFontBitmap(
    data, 0, ptsize * s, self->image.data, w, h, 0, 128, self->glyphs);

  /* Retry with a larger image buffer if the buffer wasn't large enough */
  if (res < 0) {
    w <<= 1;
    h <<= 1;
    image_deinit(&self->image);
    goto retry;
  }

  /* Adjust glyph yoffsets */
  int scaledAscent = ascent * scale + 0.5;
  for (i = 0; i < 128; i++) {
    self->glyphs[i].yoff += scaledAscent;
  }

  /* Init image data and mask */
  for (i = 0; i < w * h; i++) {
    self->image.data[i] = (self->image.data[i] > 127) ? 1 : 0;
    self->image.mask[i] = (self->image.data[i] == 0) ? 0xff : 0;
  }

  /* Return NULL for no error */
  return NULL;
}
Beispiel #2
0
	int FontRenderer::getKerning(const fm::Uint32 &leftCodePoint,const fm::Uint32 &rightCodePoint) const
	{
		if (!m_fileContent)
			return 0;
		
		return stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_stbFontInfo, m_currentSize) * stbtt_GetCodepointKernAdvance((stbtt_fontinfo*)m_stbFontInfo, leftCodePoint,rightCodePoint);
	}
Beispiel #3
0
	fm::rect2i FontRenderer::getGlyphRect(const fm::Uint32 &letter,Glyph::Style /* style */) const
	{
		float scale = stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_stbFontInfo, m_currentSize);
			
		int ix0,ix1,iy0,iy1;
		stbtt_GetCodepointBitmapBox((stbtt_fontinfo*)m_stbFontInfo, letter, scale, scale, &ix0, &iy0, &ix1, &iy1);
		
		int leftSideBearing, advanceWidth;
		stbtt_GetCodepointHMetrics((stbtt_fontinfo*)m_stbFontInfo, letter, &advanceWidth, &leftSideBearing);
		
		return fm::rect2i(fm::vec2i(leftSideBearing*scale,iy0),fm::vec2i(ix1-ix0,iy1-iy0));
	}	
Beispiel #4
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;
}
Beispiel #5
0
	const FontRenderer &FontRenderer::setCharacterSize(unsigned int size) const
	{
		if (m_currentSize == size)
			return *this;
			
		m_currentSize = size;
			
		if (!m_fileContent)
			return *this;
		
		stbtt_GetFontVMetrics((stbtt_fontinfo*)m_stbFontInfo,&m_metrics.maxH,&m_metrics.minH,&m_metrics.lineGap);
		
		float scl = stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_stbFontInfo, m_currentSize);
		m_metrics.lineGap += m_metrics.maxH - m_metrics.minH;
		m_metrics.lineGap *= scl;
		m_metrics.minH *= scl;
		m_metrics.maxH *= scl;
		
		return *this;
	}
Beispiel #6
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;
}
Beispiel #7
0
	fg::Image FontRenderer::renderGlyph(const fm::Uint32 &letter,Glyph::Style style,fm::vec2 *leftDown) const
	{
		if (!m_fileContent) 
			return fg::Image();
		
		if (letter == ' ')
		{
			float scl = stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_stbFontInfo, m_currentSize);
			
			int ix0,ix1,iy0,iy1;
			
			stbtt_GetCodepointBitmapBox((stbtt_fontinfo*)m_stbFontInfo, 'w', scl, scl, &ix0, &iy0, &ix1, &iy1);
			
			return fg::Image(fm::vec2s(ix1-ix0,iy1-iy0),fg::Color(255,255,255,0));
		}
		
		unsigned char *bitmap;
		fm::vec2i size,offset;

		bitmap = stbtt_GetCodepointBitmap((stbtt_fontinfo*)m_stbFontInfo, 0,stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_stbFontInfo, m_currentSize), letter, &size.w, &size.h, &offset.x, &offset.y);
		
		if (leftDown)
			*leftDown = offset;
		
		fg::Image img;
		img.create(size);
		
		Cv(size)
			img.set(p,fg::Color(255,bitmap[p.x + p.y*size.w]));
		
		stbtt_FreeBitmap(bitmap,0);
		
		return img;
		
		(void)style;
/*
		// if rendering upper/lower index decrease size
		unsigned int originalSize = m_currentSize;
		if ((style & Glyph::Subscript) xor (style & Glyph::Superscript ))
			setCharacterSize(m_currentSize*.7);

		// get glyph index
		FT_UInt glyphIndex = FT_Get_Char_Index(*((FT_Face*)m_ftFaceData),letter);

		// load glyph data
		int error = FT_Load_Glyph(*((FT_Face*)m_ftFaceData),glyphIndex,FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT);

		if (error)
			return fg::Image();

		FT_Face face = (*((FT_Face*)m_ftFaceData));

		// embolden and italicise
		if (style & fg::Glyph::Bold)
			FT_GlyphSlot_Embolden(face->glyph);

		if (style & fg::Glyph::Italic)
			FT_GlyphSlot_Oblique(face->glyph);

		// render glyph image
		error = FT_Render_Glyph( face->glyph,FT_RENDER_MODE_NORMAL);

		if (error)
			return fg::Image();

		// get bitmap details
		fm::Size width  = face->glyph->bitmap.width;
		fm::Size height = face->glyph->bitmap.rows;

		std::vector<fm::Uint8> bitmap(face->glyph->bitmap.buffer,face->glyph->bitmap.buffer+width*height);

		float offsetx = (face->glyph->metrics.horiBearingX>>6);
		float offsety = (face->glyph->metrics.horiBearingY>>6)-float(height);

		// manually create upper index if requested
		if (style & fg::Glyph::Superscript && !(style & fg::Glyph::Subscript))
		{
			fm::Size deltaH = height*0.4f;
			bitmap.resize(width*(height+deltaH),0);
			offsety+=deltaH;
			height+=deltaH;
		}

		// manually create lower index if requested
		if (style & fg::Glyph::Subscript && !(style & fg::Glyph::Superscript))
		{
			fm::Size deltaH = height*0.4f;
			bitmap.resize(width*(height+deltaH),0);
			offsety-=deltaH;
			Cxy(width,height)
			{
				fm::Uint8 tmp = bitmap[x+int(height+deltaH-y-1)*width];
				bitmap[x+int(height+deltaH-y-1)*width] = bitmap[x+int(height-y-1)*width];
				bitmap[x+int(height-y-1)*width] = tmp;
			}
			height+=height/2.f;
		}

		// reset the size back if needed
		if ((style & fg::Glyph::Subscript) xor (style & fg::Glyph::Superscript))
			setCharacterSize(originalSize);

		// manually strike through and/or underline if requested
		for (int i=0;i<bool(style & fg::Glyph::Crossed)+bool(style & fg::Glyph::Underlined);i++)
		{
			bool crossed = ((style & fg::Glyph::Crossed) && i==0);

			int ymax = offsety+height;
			float &ymin = offsety;

			// if the line would be out of the image (take account the y offset like in '~' as the leeter might not "sit" on the baseline)
			int lineW = int(m_metrics.maxH/15.f);
			int lineP = int(m_metrics.maxH*(crossed ? 0.2 : 0.0) );
			if (ymin > lineP)
			{
				bitmap.resize(width*(height+int(ymin-lineP)),0);

				ymin = lineP;
				height = ymax-ymin;
			}
			else if (ymax < lineW+lineP)
			{
				bitmap.resize(width*(height+(lineW+lineP-ymax)),0);

				ymax = lineW+lineP;
				height = ymax-ymin;
			}

			// simply set the value to one for every pixel in the line
			Cx(width)
				Cy((unsigned int)(lineW))
					bitmap[x+(height-1-y+int(ymin)-lineP)*width] = 255;
		}

		// manually create outline if requested
		if (style & fg::Glyph::Outline)
		{
			std::vector<fm::Uint8> oldData = bitmap;

			bitmap.resize((width+2)*(height+2));

			// get a bigger bitmap
			Cxy(width+2,height+2)
			{
				int db=0,sum=0;
				int ax=int(x)-1,ay=int(y)-1;
				int curVal = fm::rect2i(0,0,width-1,height-1).contains(fm::vec2i(ax,ay)) ? oldData[ax+ay*width] : 0;

				// this algorithm uses the difference between the neighbour pixels (the bigger the difference the bigger the output will be)
				for(int x1=-1;x1<=1;x1++) for(int y1=-1;y1<=1;y1++)
				{
					if (fm::vec2(x1,y1).LENGTH()>=1)
					{
						int deltaVal=(fm::rect2i(0,0,width-1,height-1).contains(fm::vec2i(ax+x1,ay+y1))) ? oldData[(ax+x1)+(ay+y1)*width]-curVal : -curVal;
						deltaVal*=(deltaVal > 0 ? .9 : 1.4);
						sum+=(deltaVal < 0 ? -deltaVal : deltaVal),
						db++;
					}
				}

				// do some scaling on the value and clamp it to [0;255]
				bitmap[x+y*(width+2)] = fm::math::min(255.0,db ? sum/db*1.6 : 0.0);
			}

			// update glyph image details
			width+=2,height+=2;offsetx--,offsety--;
		}

		Cxy(width,height)
		{
			float f = bitmap[y*width + x] / 255.0;
			bitmap[y*width + x] = fm::math::sqrt3(f) * 255.0;
		}

		if (leftDown)
			leftDown->x = offsetx,
			leftDown->y = offsety;

		// convert the bitmap to fg::Image
		fg::Image img;
		img.create(width,height);

		Cxy(width,height)
			img.setPixel(x,y,fg::Color(255,255,255,bitmap[y*width + x]));
*/
		return img;
	}
Beispiel #8
0
void Text::setText(const char* text)
{
	int length = strlen(text);
	if(length > 255) length = 255;

	memset(pTextBuffer, 0x00, 256);
	memcpy(pTextBuffer, text, length);

	const char* p;

	int width=0,height=0;

    /* calculate font scaling */
	LOCK_ACQUIRE(gFtLock);
    //float scale = stbtt_ScaleForPixelHeight(gFontInfo, pPixelSize);
    float scale = stbtt_ScaleForMappingEmToPixels(gFontInfo, pPixelSize);

    int ascent, descent, lineGap;
    stbtt_GetFontVMetrics(gFontInfo, &ascent, &descent, &lineGap);

    ascent *= scale;
    descent *= scale;

    height = ascent;
    // calculate bitmap size
    for (p = pTextBuffer; *p; p++)
    {
        /* how wide is this character */
        int ax;
        stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0);
        width += ax * scale;

        /* add kerning */
        int kern;
        kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]);
        width += kern * scale;
    }

    //check if old bitmap exists, and delete it
	uint8_t* oldBitmap = pBitmap;
	pBitmap = (uint8_t*)malloc(width*height);
	if(oldBitmap)
	{
		free(oldBitmap);
	}


	memset(pBitmap,0,width*height);

	pBitmapWidth = width;
	pBitmapHeight = height;

	setSizeN(
			2.f*((float)pBitmapWidth)/GetCore()->screen_width,
			2.f*((float)pBitmapHeight)/GetCore()->screen_width
	);

	int x=0,y=0;

	// render text to buffer
	for (p = pTextBuffer; *p; p++)
    {
        /* get bounding box for character (may be offset to account for chars that dip above or below the line */
        int c_x1, c_y1, c_x2, c_y2;
        stbtt_GetCodepointBitmapBox(gFontInfo, p[0], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);

        /* compute y (different characters have different heights */
        y = ascent + c_y1;

        /* render character (stride and offset is important here) */
        int byteOffset = x + (y  * width);
        stbtt_MakeCodepointBitmap(gFontInfo, pBitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, width, scale, scale, p[0]);

        /* how wide is this character */
        int ax;
        stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0);
        x += ax * scale;

        /* add kerning */
        int kern;
        kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]);
        x += kern * scale;
    }
	LOCK_RELEASE(gFtLock);

	updateBitmap = true;
}