void DynamicFontData::set_font_data(const DVector<uint8_t>& p_font) { //clear caches and stuff ERR_FAIL_COND(font_data.size()) ; font_data=p_font; lock(); if (valid) { stbtt_GetFontVMetrics(&info, &ascent, &descent, &linegap); descent=-descent + linegap; for(int i=32;i<1024;i++) { for(int j=32;j<1024;j++) { int kern = stbtt_GetCodepointKernAdvance(&info, i,j); if (kern!=0) { KerningPairKey kpk; kpk.A=i; kpk.B=j; kerning_map[kpk]=kern; } } } } unlock(); //clear existing stuff ERR_FAIL_COND(!valid); }
TruetypeFont::TruetypeFont(const DataPtr& inData, uint32_t inSizeInPoints) { const unsigned char* data = reinterpret_cast<unsigned char*>(inData->bytes.get()); _fontinfo = (stbtt_fontinfo*)malloc(sizeof(stbtt_fontinfo)); memset(_fontinfo, 0, sizeof(stbtt_fontinfo)); _data = inData; ASSERT(stbtt_InitFont(_fontinfo, data, 0), "font init failed") size = inSizeInPoints; atlasSize.width = 256; atlasSize.height = 256; _vscale = stbtt_ScaleForPixelHeight(_fontinfo, size); int ascent = 0; int descent = 0; int lineGap = 0; stbtt_GetFontVMetrics(_fontinfo, &ascent, &descent, &lineGap); ascender = floorf(ascent*_vscale); descender = floorf(descent*_vscale); lineHeight = floorf((ascent - descent + lineGap)*_vscale); // DOUT("font ascender:"<<ascender<<" descender:"<<descender<<" lineHeight:"<<lineHeight); rebuildTextureAtlas(); }
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); } } }
int DaoxFont_Init( DaoxFont *self, DString *ttfData ) { DString_Assign( self->buffer, ttfData ); if( stbtt_InitFont( & self->info, (uchar_t*) self->buffer->chars, 0 ) == 0 ) return 0; stbtt_GetFontVMetrics( & self->info, & self->ascent, & self->descent, & self->lineSpace ); self->fontHeight = self->ascent - self->descent; self->lineSpace += self->fontHeight; return 1; }
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; } }
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; }
s32 cellFontGetHorizontalLayout(vm::ptr<CellFont> font, vm::ptr<CellFontHorizontalLayout> layout) { cellFont.Log("cellFontGetHorizontalLayout(font=*0x%x, layout=*0x%x)", font, layout); s32 ascent, descent, lineGap; float scale = stbtt_ScaleForPixelHeight(font->stbfont, font->scale_y); stbtt_GetFontVMetrics(font->stbfont, &ascent, &descent, &lineGap); layout->baseLineY = ascent * scale; layout->lineHeight = (ascent-descent+lineGap) * scale; layout->effectHeight = lineGap * scale; return CELL_OK; }
bool FontAtlas::generate() { generated = false; std::array<int, kMaxGlyphs> glyphs; int numGlyphs = glyphsForCategory(glyphCategory, glyphs); packData->charData.resize(numGlyphs); stbtt_pack_range packRange; packRange.font_size = fontSize; packRange.first_unicode_codepoint_in_range = 0; packRange.array_of_unicode_codepoints = glyphs.data(); packRange.num_chars = numGlyphs; packRange.chardata_for_range = packData->charData.data(); UPtr<unsigned char[]> textureData; stbtt_pack_context packContext; bool packed = pack(font, &packContext, &packRange, &textureData, &textureWidth, &textureHeight); if (!packed) { return false; } stbtt_fontinfo fontInfo; int res = stbtt_InitFont(&fontInfo, font->data(), stbtt_GetFontOffsetForIndex(font->data(), 0)); if (!res) { return false; } float scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize); int ascent, descent, lineGap; stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap); fontSpacing.ascent = ascent * scale; fontSpacing.descent = descent * scale; fontSpacing.lineGap = lineGap * scale; texture = std::make_shared<Texture>(GL_TEXTURE_2D); texture->bind(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, textureWidth, textureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, textureData.get()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texture->unbind(); generated = true; return true; }
bool StbFontRenderer::GetFontProperties( const FontPtr& d, scalar h, FontProperties& p) { if(!d) return false; p.scale = stbtt_ScaleForPixelHeight(&d->info, h); stbtt_GetFontVMetrics(&d->info, &p.ascent, &p.descent, &p.linegap); p.ascent *= p.scale; p.descent *= p.scale; return true; }
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; }
DAO_DLL int DaoFont_OnLoad( DaoVmSpace *vmSpace, DaoNamespace *ns ) { DaoxFont *font; daox_type_font = DaoNamespace_WrapType( ns, & DaoxFont_Typer, 0 ); daox_type_glyph = DaoNamespace_WrapType( ns, & DaoxGlyph_Typer, 0 ); daox_default_font = font = DaoxFont_New(); DaoNamespace_AddConstValue( ns, "DefaultFont", (DaoValue*) font ); if( stbtt_InitFont( & font->info, daox_courier_code_roman_font_data, 0 ) == 0 ) return 1; stbtt_GetFontVMetrics( & font->info, & font->ascent, & font->descent, & font->lineSpace ); font->fontHeight = font->ascent - font->descent; font->lineSpace += font->fontHeight; return 0; }
void *textLoadFont(const char *fname, int size, int tex_w, int tex_h) { TEXT_FONT *font; FILESYSTEM_FILE *fp; int flen, asc, desc, linegap; if ((font = malloc(sizeof(TEXT_FONT))) == NULL) { return NULL; } if ((fp = fsFileOpen(fname, "rb")) == NULL) { fprintf(stderr, "Unable to open file %s\n", fname); free(font); return NULL; } fsFileSeek(fp, 0, SEEK_END); flen = fsFileTell(fp); fsFileSeek(fp, 0, SEEK_SET); if ((font->font_data = malloc(flen)) == NULL) { fsFileClose(fp); free(font); return NULL; } fsFileRead(font->font_data, flen, fp); font->font_data_len = flen; fsFileClose(fp); if (stbtt_InitFont(&font->face, font->font_data, 0) == 0) { free(font->font_data); free(font); return NULL; } font->cache = NULL; font->font_height = size; font->tex_w = bitwiseRoundUpToPow2(tex_w); font->tex_h = bitwiseRoundUpToPow2(tex_h); font->scale = stbtt_ScaleForPixelHeight(&font->face, font->font_height); stbtt_GetFontVMetrics(&font->face, &asc, &desc, &linegap); font->line_gap = font->scale * linegap; font->ascent = font->scale * asc; font->descent = font->scale * desc; return font; }
JNIEXPORT void JNICALL Java_com_badlogic_gdx_graphics_g2d_stbtt_StbTrueType_getFontVMetrics(JNIEnv* env, jclass clazz, jlong info, jintArray obj_metrics) { int* metrics = (int*)env->GetPrimitiveArrayCritical(obj_metrics, 0); //@line:57 int ascent = 0; int descent = 0; int lineGap = 0; stbtt_GetFontVMetrics((stbtt_fontinfo*)info, &ascent, &descent, &lineGap); metrics[0] = ascent; metrics[1] = descent; metrics[2] = lineGap; env->ReleasePrimitiveArrayCritical(obj_metrics, metrics, 0); }
int cellFontGetHorizontalLayout(mem_ptr_t<CellFont> font, mem_ptr_t<CellFontHorizontalLayout> layout) { cellFont->Log("cellFontGetHorizontalLayout(font_addr=0x%x, layout_addr=0x%x)", font.GetAddr(), layout.GetAddr()); if (!font.IsGood() || !layout.IsGood()) return CELL_FONT_ERROR_INVALID_PARAMETER; int ascent, descent, lineGap; float scale = stbtt_ScaleForPixelHeight(&(font->stbfont), font->scale_y); stbtt_GetFontVMetrics(&(font->stbfont), &ascent, &descent, &lineGap); layout->baseLineY = ascent * scale; layout->lineHeight = (ascent-descent+lineGap) * scale; layout->effectHeight = lineGap * scale; return CELL_FONT_OK; }
void Ibex::TextRenderer::initializeFont() { unsigned char *ttf_buffer = new unsigned char[1<<22]; unsigned char *temp_bitmap = new unsigned char[1024*256];//512*512]; #ifdef WIN32 //size_t read = fread(ttf_buffer, 1, 1<<22, fopen("c:/windows/fonts/times.ttf", "rb")); //size_t read = fread(ttf_buffer, 1, 1<<22, fopen("c:/windows/fonts/Courbd.ttf", "rb")); size_t read = fread(ttf_buffer, 1, 1<<22, fopen("c:/windows/fonts/L_10646.ttf", "rb")); #else //size_t read = fread(ttf_buffer, 1, 1<<22, fopen("/Library/Fonts/Georgia.ttf", "rb")); size_t read = fread(ttf_buffer, 1, 1<<22, fopen("/Library/Fonts/Andale Mono.ttf", "rb")); //size_t read = fread(ttf_buffer, 1, 1<<22, fopen("/Library/Fonts/OsakaMono.ttf", "rb")); #endif std::cerr << "Read font bytes: " << read << std::endl; stbtt_fontinfo font; stbtt_InitFont(&font, ttf_buffer, 0); int r = stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,1024,256, 32,96, cdata); // no guarantee this fits! if(r <= 0) { std::cerr << "stbtt_BackFontBitmap r: " << r << std::endl; exit(0); } scale = stbtt_ScaleForPixelHeight(&font, 32); stbtt_GetFontVMetrics(&font, &ascent,&descent,&lineGap); baseline = (int) (ascent*scale); // can free ttf_buffer at this point if(ftex == 0) glGenTextures(1, &ftex); glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)1024); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, ftex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1024,256, 0, GL_RED, GL_UNSIGNED_BYTE, temp_bitmap); // can free temp_bitmap at this point if(!checkForErrors()) { exit(1); } delete []ttf_buffer; delete []temp_bitmap; }
float* get_font_data(const char *font_file, float *font_height){ float *data = 0; stbtt_bakedchar *baked; File_Data file = get_file(font_file); if (!file.data) exit(1); if (file.data){ int size = sizeof(*baked)*256; baked = (stbtt_bakedchar*)malloc(size); memset_4tech(baked, 0, sizeof(*baked)*256); stbtt_fontinfo font; if (stbtt_InitFont(&font, (unsigned char*)file.data, 0)){ float scale; int a,d,g; scale = stbtt_ScaleForPixelHeight(&font, 17.f); stbtt_GetFontVMetrics(&font, &a, &d, &g); *font_height = scale*(a - d + g); int w, h; w = 10*256; h = 25; unsigned char *pixels = (unsigned char*)malloc(w * h); stbtt_BakeFontBitmap((unsigned char*)file.data, 0, 17.f, pixels, w, h, 0, 128, baked); free(pixels); free_file(file); data = (float*)malloc(sizeof(float)*256); memset_4tech(data, 0, sizeof(float)*256); stbtt_bakedchar *baked_ptr = baked; for (int i = 0; i < 128; ++i, ++baked_ptr){ data[i] = baked_ptr->xadvance; } } free(baked); } else{ printf("error: cannot continue without font\n"); } return data; }
s32 cellFontRenderCharGlyphImage(vm::ptr<CellFont> font, u32 code, vm::ptr<CellFontRenderSurface> surface, float x, float y, vm::ptr<CellFontGlyphMetrics> metrics, vm::ptr<CellFontImageTransInfo> transInfo) { cellFont.notice("cellFontRenderCharGlyphImage(font=*0x%x, code=0x%x, surface=*0x%x, x=%f, y=%f, metrics=*0x%x, trans=*0x%x)", font, code, surface, x, y, metrics, transInfo); if (!font->renderer_addr) { return CELL_FONT_ERROR_RENDERER_UNBIND; } // Render the character s32 width, height, xoff, yoff; float scale = stbtt_ScaleForPixelHeight(font->stbfont, font->scale_y); unsigned char* box = stbtt_GetCodepointBitmap(font->stbfont, scale, scale, code, &width, &height, &xoff, &yoff); if (!box) { return CELL_OK; } // Get the baseLineY value s32 baseLineY; s32 ascent, descent, lineGap; stbtt_GetFontVMetrics(font->stbfont, &ascent, &descent, &lineGap); baseLineY = (int)((float)ascent * scale); // ??? // Move the rendered character to the surface unsigned char* buffer = vm::_ptr<unsigned char>(surface->buffer.addr()); for (u32 ypos = 0; ypos < (u32)height; ypos++) { if ((u32)y + ypos + yoff + baseLineY >= (u32)surface->height) break; for (u32 xpos = 0; xpos < (u32)width; xpos++) { if ((u32)x + xpos >= (u32)surface->width) break; // TODO: There are some oddities in the position of the character in the final buffer buffer[((s32)y + ypos + yoff + baseLineY)*surface->width + (s32)x + xpos] = box[ypos * width + xpos]; } } stbtt_FreeBitmap(box, 0); return CELL_OK; }
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; }
bool stash::add_font( const std::vector<unsigned char> &data, const std::string &alias ) { if( !tex ) { // Create texture for the cache. glGenTextures(1, &tex); if( !tex ) return false; glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tw,th, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } sth_font fnt(tex, &rows, tw, th); // Init stb_truetype if( data.size() && stbtt_InitFont(&fnt.font, &data[0], 0) ) { // Read in the font data. fnt.data = data; // Store normalized line height. The real line height is got // by multiplying the lineh by font size. int ascent, descent, lineGap; stbtt_GetFontVMetrics(&fnt.font, &ascent, &descent, &lineGap); int fh = ascent - descent; fnt.ascender = (float)ascent / (float)fh; fnt.descender = (float)descent / (float)fh; fnt.lineh = (float)(fh + lineGap) / (float)fh; fonts.push_back( fnt ); aliases[ alias ] = fonts.size() - 1; // refresh data pointers because of std::vector reordering for( size_t i = 0; i < fonts.size(); ++i ) fonts[i].font.data = &fonts[i].data[0]; return true; } return false; }
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; }
int cellFontRenderCharGlyphImage(mem_ptr_t<CellFont> font, u32 code, mem_ptr_t<CellFontRenderSurface> surface, float x, float y, mem_ptr_t<CellFontGlyphMetrics> metrics, mem_ptr_t<CellFontImageTransInfo> transInfo) { x = GetCurrentPPUThread().FPR[1]; // TODO: Something is wrong with the float arguments y = GetCurrentPPUThread().FPR[2]; // TODO: Something is wrong with the float arguments cellFont->Log("cellFontRenderCharGlyphImage(font_addr=0x%x, code=0x%x, surface_addr=0x%x, x=%f, y=%f, metrics_addr=0x%x, trans_addr=0x%x)", font.GetAddr(), code, surface.GetAddr(), x, y, metrics.GetAddr(), transInfo.GetAddr()); if (!font.IsGood() || !surface.IsGood() || !metrics.IsGood() || !transInfo.IsGood()) return CELL_FONT_ERROR_INVALID_PARAMETER; if (!font->renderer_addr) return CELL_FONT_ERROR_RENDERER_UNBIND; // Render the character int width, height, xoff, yoff; float scale = stbtt_ScaleForPixelHeight(&(font->stbfont), font->scale_y); unsigned char* box = stbtt_GetCodepointBitmap(&(font->stbfont), scale, scale, code, &width, &height, &xoff, &yoff); if (!box) return CELL_OK; // Get the baseLineY value int baseLineY; int ascent, descent, lineGap; stbtt_GetFontVMetrics(&(font->stbfont), &ascent, &descent, &lineGap); baseLineY = ascent * scale; // Move the rendered character to the surface unsigned char* buffer = (unsigned char*)Memory.VirtualToRealAddr(surface->buffer_addr); for (u32 ypos = 0; ypos < (u32)height; ypos++){ if ((u32)y + ypos + yoff + baseLineY >= surface->height) break; for (u32 xpos = 0; xpos < (u32)width; xpos++){ if ((u32)x + xpos >= surface->width) break; // TODO: There are some oddities in the position of the character in the final buffer buffer[((int)y + ypos + yoff + baseLineY)*surface->width + (int)x+xpos] = box[ypos*width + xpos]; } } stbtt_FreeBitmap(box, 0); return CELL_FONT_OK; }
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; }
float Face::leading(float scale) const { int ascender, descender, leading; stbtt_GetFontVMetrics(m_info, &ascender, &descender, &leading); return (ascender - descender + leading) * scale; }
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; } }
bool D3D9DebugManager::InitFontRendering() { HRESULT hr = S_OK; int width = FONT_TEX_WIDTH; int height = FONT_TEX_HEIGHT; string font = GetEmbeddedResource(sourcecodepro_ttf); byte *ttfdata = (byte *)font.c_str(); const int firstChar = int(' ') + 1; const int lastChar = 127; const int numChars = lastChar - firstChar; byte *buf = new byte[width * height]; const float pixelHeight = 20.0f; stbtt_BakeFontBitmap(ttfdata, 0, pixelHeight, buf, width, height, firstChar, numChars, m_Font.charData); stbtt_fontinfo f = {0}; stbtt_InitFont(&f, ttfdata, 0); int ascent = 0; stbtt_GetFontVMetrics(&f, &ascent, NULL, NULL); m_Font.maxHeight = float(ascent) * stbtt_ScaleForPixelHeight(&f, pixelHeight); IDirect3DTexture9 *fontTex = NULL; hr = m_WrappedDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fontTex, NULL); if(FAILED(hr)) { RDCERR("Failed to create font texture %08x", hr); } D3DLOCKED_RECT lockedRegion; hr = fontTex->LockRect(0, &lockedRegion, NULL, D3DLOCK_DISCARD); if(FAILED(hr)) { RDCERR("Failed to lock font texture %08x", hr); } else { BYTE *texBase = (BYTE *)lockedRegion.pBits; for(int y = 0; y < height; y++) { byte *curRow = (texBase + (y * lockedRegion.Pitch)); for(int x = 0; x < width; x++) { curRow[x * 4 + 0] = buf[(y * width) + x]; curRow[x * 4 + 1] = buf[(y * width) + x]; curRow[x * 4 + 2] = buf[(y * width) + x]; curRow[x * 4 + 3] = buf[(y * width) + x]; } } hr = fontTex->UnlockRect(0); if(hr != S_OK) { RDCERR("Failed to unlock font texture %08x", hr); } } m_Font.Tex = fontTex; delete[] buf; return true; }
void Font::drawStringToBuffer(int x, int y, const std::wstring& str, Color color, unsigned char* buffer, int buffer_width, int buffer_height, int bitsperpixel, int max_width) { std::vector<unsigned char> char_raster; int bx, by, bw, bh; int ascent, descent, lineGap; int sx = 0, sy = 0; int width, height; stbtt_GetFontVMetrics(&m_info, &ascent, &descent, &lineGap); ascent *= m_scale; descent *= m_scale; lineGap *= m_scale; this->measureText(str, width, height, max_width); for (unsigned 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 char_width = bw - bx; int char_height = bh - by; int oy = ascent + by; if(max_width > 0 && sx + char_width > max_width) { sy += ascent - descent + lineGap; sx = 0; } char_raster.resize(char_width * char_height); stbtt_MakeCodepointBitmap(&m_info, &char_raster[0], char_width, char_height, char_width, m_scale, m_scale, str[i]); for (int ix = 0; ix < char_width; ix++) { for (int iy = 0; iy < char_height; iy++) { int xpos = x + sx + ix; int ypos = buffer_height - (y + sy + oy + iy) -1; if (char_raster[ix + iy * char_width] != 0 && xpos < buffer_width && ypos < buffer_height) { unsigned int alpha = char_raster[ix + iy * char_width]; unsigned int inv_alpha = 255 - alpha; if (bitsperpixel == 24) { unsigned char bg_r = buffer[3 * (xpos + ypos * buffer_width) + 0]; unsigned char bg_g = buffer[3 * (xpos + ypos * buffer_width) + 1]; unsigned char bg_b = buffer[3 * (xpos + ypos * buffer_width) + 2]; unsigned char r = (unsigned char)((alpha * color.r + inv_alpha * bg_r) >> 8); unsigned char g = (unsigned char)((alpha * color.g + inv_alpha * bg_g) >> 8); unsigned char b = (unsigned char)((alpha * color.b + inv_alpha * bg_b) >> 8); buffer[3 * (xpos + ypos * buffer_width) + 0] = b; buffer[3 * (xpos + ypos * buffer_width) + 1] = g; buffer[3 * (xpos + ypos * buffer_width) + 2] = r; } else { unsigned char bg_r = buffer[4 * (xpos + ypos * buffer_width) + 0]; unsigned char bg_g = buffer[4 * (xpos + ypos * buffer_width) + 1]; unsigned char bg_b = buffer[4 * (xpos + ypos * buffer_width) + 2]; unsigned char bg_a = buffer[4 * (xpos + ypos * buffer_width) + 3]; unsigned char a; if(alpha == 255 || bg_a == 255) { a = 255; } else { a = alpha + (inv_alpha * bg_a) / 256; } unsigned int r,g,b; if(a == 0) { r = 0; g = 0; b = 0; } else { r = (alpha * color.r + (inv_alpha * bg_a * bg_r) / 256) / a; b = (alpha * color.b + (inv_alpha * bg_a * bg_b) / 256) / a; g = (alpha * color.g + (inv_alpha * bg_a * bg_g) / 256) / a; } buffer[4 * (xpos + ypos * buffer_width) + 0] = b > 255 ? 255 : b; buffer[4 * (xpos + ypos * buffer_width) + 1] = g > 255 ? 255 : g; buffer[4 * (xpos + ypos * buffer_width) + 2] = r > 255 ? 255 : r; buffer[4 * (xpos + ypos * buffer_width) + 3] = a; } } }
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; }
float Face::descender(float scale) const { int descender; stbtt_GetFontVMetrics(m_info, nullptr, &descender, nullptr); return descender * scale; }