Example #1
0
int __stdcall get_width(char *text, char *buffer, int height)
{

stbtt_fontinfo font;
   int i,j,ascent,baseline,ch,xpos=0;
   float scale=0;
   
   baseline=10;
 
  if (buffer==-1) {stbtt_InitFont(&font, pdf_font_DroidSans,stbtt_GetFontOffsetForIndex(pdf_font_DroidSans,0) );} else {stbtt_InitFont(&font, buffer,stbtt_GetFontOffsetForIndex(buffer,0) );kol_board_puts("Font loaded..\n");}
kol_board_puts("Engine init..\n");
//kol_board_puti(&screen);
   scale = stbtt_ScaleForPixelHeight(&font, height*3/4);
   int advance,lsb;
   
 while (dos2utf(text[ch])) {
//	   kol_board_puts("new symbol...\n");
    
       stbtt_GetCodepointHMetrics(&font, dos2utf(text[ch]), &advance, &lsb);
  xpos += (advance * scale);
      if (text[ch+1])
         xpos += scale*stbtt_GetCodepointKernAdvance(&font, dos2utf(text[ch]),dos2utf(text[ch+1]));
      ++ch;
   }
   stbtt_GetCodepointHMetrics(&font, dos2utf(text[ch]), &advance, &lsb);
     xpos += (advance * scale);
   return xpos;

}
Example #2
0
float Font::measureText(const std::string& text)
{	
	float length = 0.0f;
	float lineLength = 0.0f;
	
	if(isLoaded())
	{
		for(unsigned int i = 0; i < text.length(); i++)
		{
			if(text[i] == '\n')
			{
				if(lineLength > length) {
					length = lineLength;
				}
				
				lineLength = 0.0f;
				continue;
			}
			
			int advance = 0;
			stbtt_GetCodepointHMetrics(&m_info, text[i], &advance, 0);
			
			lineLength += advance;
		}
		
		if(lineLength > length)
			length = lineLength;
	}
	
	return length;
}
Example #3
0
int cellFontGetCharGlyphMetrics(mem_ptr_t<CellFont> font, u32 code, mem_ptr_t<CellFontGlyphMetrics> metrics)
{
	cellFont->Log("cellFontGetCharGlyphMetrics(font_addr=0x%x, code=0x%x, metrics_addr=0x%x",
		font.GetAddr(), code, metrics.GetAddr());

	if (!font.IsGood() || metrics.IsGood())
		return CELL_FONT_ERROR_INVALID_PARAMETER;

	int x0, y0, x1, y1;
	int advanceWidth, leftSideBearing;
	float scale = stbtt_ScaleForPixelHeight(&(font->stbfont), font->scale_y);
	stbtt_GetCodepointBox(&(font->stbfont), code, &x0, &y0, &x1, &y1);
	stbtt_GetCodepointHMetrics(&(font->stbfont), code, &advanceWidth, &leftSideBearing);
	
	// TODO: Add the rest of the information
	metrics->width = (x1-x0) * scale;
	metrics->height = (y1-y0) * scale;
	metrics->Horizontal.bearingX = (float)leftSideBearing * scale;
	metrics->Horizontal.bearingY = 0;
	metrics->Horizontal.advance = (float)advanceWidth * scale;
	metrics->Vertical.bearingX = 0;
	metrics->Vertical.bearingY = 0;
	metrics->Vertical.advance = 0;
	return CELL_FONT_OK;
}
Example #4
0
void UniFont::CacheGlyphDefault(const unsigned int* str, int index, int len, int cellCols, int cellRows, Texture* tex, bool* outIsDirty) {
	int codePoint = str[index];
	int charSize = fontScale + 2;
	if (GetInfoForCodepoint(codePoint) == nullptr) {
		stbtt_fontinfo* font = nullptr;
		unsigned char* cBmp = nullptr;
		int cW = 0, cH = 0;
		for (int j = 0; j < fontInfos.count; j++) {
			if (fontInfos.data[j].low <= codePoint && codePoint <= fontInfos.data[j].high) {
				float pixelScale = stbtt_ScaleForPixelHeight(&fontInfos.data[j].info, fontScale);
				int glyphIdx = stbtt_FindGlyphIndex(&fontInfos.data[j].info, codePoint);
				cBmp = stbtt_GetCodepointBitmap(&fontInfos.data[j].info, 0, pixelScale, codePoint, &cW, &cH, 0, 0);
				if (cBmp) {
					font = &fontInfos.data[j].info;
					break;
				}
			}
		}

		if (font != nullptr) {
			*outIsDirty = true;
			int ascent, descent, lineGap;
			stbtt_GetFontVMetrics(font, &ascent, &descent, &lineGap);

			float pixelScale = stbtt_ScaleForPixelHeight(font, fontScale);

			int cellY = cacheCursor / cellCols;
			int cellX = cacheCursor % cellCols;

			int startX = cellX * charSize;
			int startY = cellY * charSize;

			GlyphBlit(tex->texMem, tex->width, tex->height, startX, startY, cBmp, cW, cH);

			free(cBmp);

			int advanceWidth = 0, leftSideBearing = 0;
			stbtt_GetCodepointHMetrics(font, codePoint, &advanceWidth, &leftSideBearing);

			int x0, y0, x1, y1;
			stbtt_GetCodepointBitmapBox(font, codePoint, pixelScale, pixelScale, &x0, &y0, &x1, &y1);
			CodepointInfo pointInfo = {};
			pointInfo.codepoint = codePoint;
			pointInfo.x = startX;
			pointInfo.y = startY;
			pointInfo.w = cW;
			pointInfo.h = cH;
			pointInfo.xOffset = x0;
			pointInfo.yOffset = y0;
			pointInfo.xAdvance = pixelScale * advanceWidth;

			codepointListing.EnsureCapacity(cacheCursor + 1);
			codepointListing.count = BNS_MAX(codepointListing.count, cacheCursor + 1);
			codepointListing.data[cacheCursor] = pointInfo;

			cacheCursor = (cacheCursor + 1) % (cellCols * cellRows);
		}
	}
}
Example #5
0
void Font::measureText(const std::wstring str, int& width, int& height, int max_width) {
	if(!isLoaded())
	{
		return NULL;
	}

	Image char_render;
	std::vector<unsigned char> char_raster;
	int bx, by, bw, bh;
	int ascent, descent, lineGap;
	int sx = 0, sy = 0;

	stbtt_GetFontVMetrics(&m_info, &ascent, &descent, &lineGap);

	ascent *= m_scale;
	descent *= m_scale;
	lineGap *= m_scale;

	width = 0;
	height = 0;

	for(int i = 0; i < str.length(); i++) {
		if(str[i] == L'\n') {
			sy += ascent - descent + lineGap;
			sx = 0;
			continue;
		}

		stbtt_GetCodepointBitmapBox(&m_info, str[i], m_scale, m_scale,
				&bx, &by, &bw, &bh);

		int cwidth = bw - bx;
		int cheight = bh - by;
		int oy = ascent + by;

		if(max_width > 0 && sx + cwidth > max_width) {
			sy += ascent - descent + lineGap;
			sx = 0;
		}

		int advance;
		stbtt_GetCodepointHMetrics(&m_info, str[i], &advance, 0);
		if(sy + oy + cheight > height) {
			height = sy + oy + cheight;
		}
		if(sx + cwidth > width) {
			width = sx + cwidth;
		}

		sx += advance * m_scale;

		int kerning = stbtt_GetCodepointKernAdvance(&m_info, str[i], str[i + 1]);

		sx += kerning * m_scale;
	}
}
Example #6
0
int __stdcall picture(char *text, char *buffer, char *screen1, int width, int height)
{

 //unsigned char *screen;
 //screen=zmalloc(20*78); 
	//kol_board_puts(screen);
	//kol_board_puts("It was text\n");
	
stbtt_fontinfo font;
   int i,j,ascent,baseline,descent,ch=0;
   float scale, xpos=0;
   
   //baseline=10;
   kol_board_puts("Font address:\n");
   //kol_board_puti(buffer);
 if (buffer==-1) {stbtt_InitFont(&font, pdf_font_DroidSans,stbtt_GetFontOffsetForIndex(pdf_font_DroidSans,0) );kol_board_puts("default font\n");} else {stbtt_InitFont(&font, buffer,stbtt_GetFontOffsetForIndex(buffer,0) );kol_board_puts("Font loaded..\n");}

//kol_board_puti(&screen);
   scale = stbtt_ScaleForPixelHeight(&font, height*3/4);
   //stbtt_GetFontVMetrics(&font, &ascent,0,0);
   stbtt_GetFontVMetrics(&font, &ascent,&descent,0); //lev
   //baseline = (int) (ascent*scale);
   baseline = (int) ((ascent-descent)*scale); //lev


//kol_board_puts("Text render:\n");

   while (dos2utf(text[ch])) {
	   //kol_board_puts("new symbol...\n");
      int advance,lsb,x0,y0,x1,y1;
      //float x_shift = xpos - (float) i_floor(xpos);
      
     // kol_board_puts("floor called!\n");
      stbtt_GetCodepointHMetrics(&font, dos2utf(text[ch]), &advance, &lsb);
      stbtt_GetCodepointBitmapBoxSubpixel(&font, dos2utf(text[ch]), scale,scale,0,0, &x0,&y0,&x1,&y1);


     //10= y0, 20=y1-y0 or so
      stbtt_MakeCodepointBitmapSubpixel(&font, &screen1[(baseline + y0)*width+ (int)xpos + x0], x1-x0,y1-y0, width, scale,scale,0,0, dos2utf(text[ch]));
       
      // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
      // because this API is really for baking character bitmaps into textures. if you want to do this,
      // you need to render the bitmap to a temp buffer, then\n\t"alpha blend" that into the working buffer
      xpos += (advance * scale);
      if (text[ch+1])
         xpos += scale*stbtt_GetCodepointKernAdvance(&font, dos2utf(text[ch]),dos2utf(text[ch+1]));
      ++ch;
   }
   
  //zmemcpy(screen1,bitmap,20*20);

//kol_board_puts("finished...\n");
return 0;
}
Example #7
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));
	}	
JNIEXPORT void JNICALL Java_com_badlogic_gdx_graphics_g2d_stbtt_StbTrueType_getCodepointHMetrics(JNIEnv* env, jclass clazz, jlong info, jint codePoint, jintArray obj_metrics) {
	int* metrics = (int*)env->GetPrimitiveArrayCritical(obj_metrics, 0);


//@line:67

		int advanceWidth = 0;
		int leftSideBearing = 0;
		stbtt_GetCodepointHMetrics((stbtt_fontinfo*)info, codePoint, &advanceWidth, &leftSideBearing);
		metrics[0] = advanceWidth;
		metrics[1] = leftSideBearing;
	
	env->ReleasePrimitiveArrayCritical(obj_metrics, metrics, 0);

}
Example #9
0
		long calculateCharAdvance(char32_t cp) override
		{
			//int advance = 0;
			//int bearing = 0;
			//stbtt_GetCodepointHMetrics(&font_handle_, cp, &advance, &bearing);
			//return static_cast<int>(advance * scale_ * 65536.0f);
			auto it = packed_char_.find(UnicodeRange(cp));
			if(it == packed_char_.end()) {
				int advance = 0;
				int bearing = 0;
				stbtt_GetCodepointHMetrics(&font_handle_, cp, &advance, &bearing);
				return static_cast<int>(advance * scale_ * 65536.0f);
			}		
			stbtt_packedchar *b = it->second.data() + cp - it->first.first;
			return static_cast<int>(b->xadvance * 65536.0f);
		}
Example #10
0
s32 cellFontGetCharGlyphMetrics(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontGlyphMetrics> metrics)
{
	cellFont.Log("cellFontGetCharGlyphMetrics(font=*0x%x, code=0x%x, metrics=*0x%x)", font, code, metrics);

	s32 x0, y0, x1, y1;
	s32 advanceWidth, leftSideBearing;
	float scale = stbtt_ScaleForPixelHeight(font->stbfont, font->scale_y);
	stbtt_GetCodepointBox(font->stbfont, code, &x0, &y0, &x1, &y1);
	stbtt_GetCodepointHMetrics(font->stbfont, code, &advanceWidth, &leftSideBearing);
	
	// TODO: Add the rest of the information
	metrics->width = (x1-x0) * scale;
	metrics->height = (y1-y0) * scale;
	metrics->Horizontal.bearingX = (float)leftSideBearing * scale;
	metrics->Horizontal.bearingY = 0.f;
	metrics->Horizontal.advance = (float)advanceWidth * scale;
	metrics->Vertical.bearingX = 0.f;
	metrics->Vertical.bearingY = 0.f;
	metrics->Vertical.advance = 0.f;
	return CELL_OK;
}
Example #11
0
bool TruetypeFont::renderGlyph(char32_t c)
{
    bool result = false;
    GlyphPtr glyph = char2glyph[c];
    if(!glyph)
    {
        result = true;
        glyph.reset(new Glyph);
//    glyph->render(face, size, c);

        int advance, lsb;
        stbtt_GetCodepointHMetrics(_fontinfo, c, &advance, &lsb);

        int ix0, iy0, ix1, iy1;
        stbtt_GetCodepointBitmapBox(_fontinfo, c, _vscale, _vscale, &ix0, &iy0, &ix1, &iy1);
        int width = ix1-ix0;
        int height = iy1-iy0;
        unsigned char* bmpmem = (unsigned char*)malloc(width*height);
        stbtt_MakeCodepointBitmapSubpixel(_fontinfo, bmpmem, width, height, width, _vscale, _vscale, .0, .0, c);

        BitmapPtr result(new Bitmap(width,
                                    height,
                                    GL_RGBA,
                                    GL_ALPHA,
                                    bmpmem));
        result->flip();
        free(bmpmem);
        glyph->bitmap = result;
        glyph->advance = floorf(advance*_vscale);
        glyph->xoffset = floorf(lsb*_vscale);
        glyph->yoffset = -iy1;

        char2glyph[c] = glyph;
        glyphs.push_back(glyph);
    }
    return result;
}
Example #12
0
void DynamicFontAtSize::_update_char(CharType p_char) {

	if (char_map.has(p_char))
		return;

	font->lock();


	int w,h,xofs,yofs;
	unsigned char * cpbitmap = stbtt_GetCodepointBitmap(&font->info, scale, scale, p_char, &w, &h, &xofs, &yofs );

	if (!cpbitmap) {
		//no glyph

		int advance;
		stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
		//print_line("char has no bitmap: "+itos(p_char)+" but advance is "+itos(advance*scale));
		Character ch;
		ch.texture_idx=-1;
		ch.advance=advance*scale;
		ch.h_align=0;
		ch.v_align=0;

		char_map[p_char]=ch;

		font->unlock();

		return;
	}

	int mw=w+rect_margin*2;
	int mh=h+rect_margin*2;

	if (mw>4096 || mh>4096) {

		stbtt_FreeBitmap(cpbitmap,NULL);
		font->unlock();
		ERR_FAIL_COND(mw>4096);
		ERR_FAIL_COND(mh>4096);
	}

	//find a texture to fit this...

	int tex_index=-1;
	int tex_x=0;
	int tex_y=0;

	for(int i=0;i<textures.size();i++) {

		CharTexture &ct=textures[i];

		if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture
			continue;

		tex_y=0x7FFFFFFF;
		tex_x=0;

		for(int j=0;j<ct.texture_size-mw;j++) {

			int max_y=0;

			for(int k=j;k<j+mw;k++) {

				int y = ct.offsets[k];
				if (y>max_y)
					max_y=y;
			}

			if (max_y<tex_y) {
				tex_y=max_y;
				tex_x=j;
			}
		}

		if (tex_y==0x7FFFFFFF || tex_y+mh > ct.texture_size)
			continue; //fail, could not fit it here

		tex_index=i;
		break;
	}

//	print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" X: "+itos(tex_x)+" Y: "+itos(tex_y));

	if (tex_index==-1) {
		//could not find texture to fit, create one

		int texsize = MAX(size*8,256);
		if (mw>texsize)
			texsize=mw; //special case, adapt to it?
		if (mh>texsize)
			texsize=mh; //special case, adapt to it?

		texsize=nearest_power_of_2(texsize);

		texsize=MIN(texsize,4096);


		CharTexture tex;
		tex.texture_size=texsize;
		tex.imgdata.resize(texsize*texsize*2); //grayscale alpha

		{
			//zero texture
			DVector<uint8_t>::Write w = tex.imgdata.write();
			for(int i=0;i<texsize*texsize*2;i++) {
				w[i]=0;
			}
		}
		tex.offsets.resize(texsize);
		for(int i=0;i<texsize;i++) //zero offsets
			tex.offsets[i]=0;

		textures.push_back(tex);
		tex_index=textures.size()-1;

	}


	//fit character in char texture

	CharTexture &tex=textures[tex_index];

	{
		DVector<uint8_t>::Write wr = tex.imgdata.write();

		for(int i=0;i<h;i++) {
			for(int j=0;j<w;j++) {

				int ofs = ( (i+tex_y+rect_margin)*tex.texture_size+j+tex_x+rect_margin)*2;
				wr[ofs+0]=255; //grayscale as 1
				wr[ofs+1]=cpbitmap[i*w+j]; //alpha as 0
			}
		}
	}

	//blit to image and texture
	{

		Image img(tex.texture_size,tex.texture_size,0,Image::FORMAT_GRAYSCALE_ALPHA,tex.imgdata);

		if (tex.texture.is_null()) {
			tex.texture.instance();
			tex.texture->create_from_image(img,Texture::FLAG_FILTER);
		} else {
			tex.texture->set_data(img); //update
		}

	}


	// update height array

	for(int k=tex_x;k<tex_x+mw;k++) {

		tex.offsets[k]=tex_y+mh;
	}

	int advance;
	stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);

	Character chr;
	chr.h_align=xofs;
	chr.v_align=yofs + get_ascent();
	chr.advance=advance*scale;
	chr.texture_idx=tex_index;


	chr.rect=Rect2(tex_x+rect_margin,tex_y+rect_margin,w,h);

	//print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" RECT: "+chr.rect+" X OFS: "+itos(xofs)+" Y OFS: "+itos(yofs));

	char_map[p_char]=chr;

	stbtt_FreeBitmap(cpbitmap,NULL);

	font->unlock();

}
Example #13
0
void Font::drawStringUnicode(int x, int y, const std::wstring& str, Color color, bool top_screen, bool side)
{
	if(!isLoaded())
	{
		return;
	}
	
	Image char_render;
	std::vector<unsigned char> char_raster;
	int bx, by, bw, bh;
	int ascent, descent, lineGap;
	int sx = 0, sy = 0;

	stbtt_GetFontVMetrics(&m_info, &ascent, &descent, &lineGap);

	ascent *= m_scale;
	descent *= m_scale;

	for (unsigned int i = 0; i < str.length(); i++)
	{
		if(str[i + 1] == L'\n') {
			sy += lineGap * m_scale;
			sx = 0;
			continue;
		}
		
		stbtt_GetCodepointBitmapBox(&m_info, str[i], m_scale, m_scale,
			&bx, &by, &bw, &bh);

		int width = bw - bx;
		int height = bh - by;

		int oy = ascent + by;

		char_raster.resize(width * height);

		stbtt_MakeCodepointBitmap(&m_info, &char_raster[0], width, height,
			width, m_scale, m_scale, str[i]);

		char_render.create(width, height, Color(0, 0, 0, 0));

		for (int ix = 0; ix < width; ix++) {
			for (int iy = 0; iy < height; iy++) {
				if (char_raster[ix + iy * width] != 0)
					char_render.putPixel(ix, iy, Color(color.r, color.g, color.b,
					char_raster[ix + iy * width]));
			}
		}

		char_render.draw(sx + x, sy + y + oy, top_screen, side);

		int advance;
		stbtt_GetCodepointHMetrics(&m_info, str[i], &advance, 0);

		sx += advance * m_scale;

		int kerning = stbtt_GetCodepointKernAdvance(&m_info, str[i], str[i + 1]);

		sx += kerning * m_scale;
	}
}
Example #14
0
void TruetypeFont::Render(const std::string &In, const Vec2 &Position, const Mat4 &Transform)
{
    const char* Text = In.c_str();
    int Line = 0;
    glm::vec3 vOffs(Position.x, Position.y + scale, 0);

    if (!IsValid)
        return;

    UpdateWindowScale();

    SetBlendingMode(BLEND_ALPHA);

    SetShaderParameters(false, false, false, false, false, true);
    WindowFrame.SetUniform(U_COLOR, Red, Green, Blue, Alpha);
    SetPrimitiveQuadVBO();

    try
    {
        utf8::iterator<const char*> it(Text, Text, Text + In.length());
        utf8::iterator<const char*> itend(Text + In.length(), Text, Text + In.length());
        for (; it != itend; ++it)
        {
            CheckCodepoint(*it); // Force a regeneration of this if necessary
            codepdata &cp = GetTexFromCodepoint(*it);
            unsigned char* tx = cp.tex;
            glm::vec3 trans = vOffs + glm::vec3(cp.xofs, cp.yofs, 0);
            glm::mat4 dx;

            if (*it == 10) // utf-32 line feed
            {
                Line++;
                vOffs.x = Position.x;
                vOffs.y = Position.y + scale * (Line + 1);
                continue;
            }

            dx = Transform * glm::translate(Mat4(), trans) * glm::scale(Mat4(), glm::vec3(cp.w, cp.h, 1));

            // do the actual draw?
            if (cp.gltx == 0)
            {
                glGenTextures(1, &cp.gltx);
                glBindTexture(GL_TEXTURE_2D, cp.gltx);

                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

                glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, cp.tw, cp.th, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tx);
            }
            else
                glBindTexture(GL_TEXTURE_2D, cp.gltx);

            WindowFrame.SetUniform(U_MVP, &(dx[0][0]));

            DoQuadDraw();

            utf8::iterator<const char*> next = it;
            next++;
            if (next != itend)
            {
                float aW = stbtt_GetCodepointKernAdvance(info.get(), *it, *next);
                int bW;
                stbtt_GetCodepointHMetrics(info.get(), *it, &bW, NULL);
                vOffs.x += aW * virtualscale + bW * virtualscale;
            }
        }
    }
#ifndef NDEBUG
    catch (utf8::exception &ex)
    {
        Utility::DebugBreak();
        Log::Logf("Invalid UTF-8 string %s was passed. Error type: %s\n", ex.what());
    }
#else
    catch (...)
    {
        // nothing
    }
#endif

    FinalizeDraw();
    Image::ForceRebind();
}
Example #15
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;
}
Example #16
0
Bytes& StbFontRenderer::RenderText(
    const FontPtr&        data,
    const FontProperties& properties,
    cstring               text,
    Bytes&                output,
    Size&                 imageSize)
{
    using irect = rect<int>;

    auto stb_data = &data->info;
    auto scale    = properties.scale;

    Bytes stringData = Bytes::CreateString(text);
    szptr bit_w      = 0;
    int   x          = 0;

    /* We use this to find kerning character */
    auto shadowChar = stringData.begin();

    for(auto c : stringData)
    {
        irect bbox = {};
        stbtt_GetCodepointBitmapBox(
            stb_data, c, scale, scale, &bbox.x, &bbox.y, &bbox.w, &bbox.h);

        int y = properties.ascent + bbox.y, ax = 0, kern = 0;

        stbtt_GetCodepointHMetrics(stb_data, c, &ax, nullptr);
        kern = stbtt_GetCodepointKernAdvance(stb_data, c, *shadowChar);

        x += scale * (ax + kern);

        imageSize.w = CMath::max<u32>(imageSize.w, x + (bbox.w - bbox.x));
        imageSize.h = CMath::max<u32>(imageSize.h, y + (bbox.h - bbox.y));
    }

    bit_w      = C_FCAST<szptr>(imageSize.w);
    output     = Bytes::Alloc(imageSize.area());
    shadowChar = stringData.begin();
    x          = 0;

    for(auto c : stringData)
    {
        ++shadowChar;

        irect bbox = {};
        stbtt_GetCodepointBitmapBox(
            stb_data, c, scale, scale, &bbox.x, &bbox.y, &bbox.w, &bbox.h);

        int y = properties.ascent + bbox.y, ax = 0, kern = 0;

        szptr offset = C_FCAST<szptr>(x + y * bit_w);

        stbtt_MakeCodepointBitmap(
            stb_data,
            &output[offset],
            (bbox.w - bbox.x),
            (bbox.h - bbox.y),
            bit_w,
            scale,
            scale,
            c);

        stbtt_GetCodepointHMetrics(stb_data, c, &ax, nullptr);
        kern = stbtt_GetCodepointKernAdvance(stb_data, c, *shadowChar);

        x += scale * (ax + kern);
    }

    return output;
}