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 __stdcall get_length(char *text, char *buffer, int height, int max_len) { 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); while (dos2utf(text[ch])) { // kol_board_puts("new symbol...\n"); int advance,lsb; stbtt_GetCodepointHMetrics(&font, dos2utf(text[ch]), &advance, &lsb); xpos += (advance * scale); if ((int)xpos>max_len) return ch; if (text[ch+1]) xpos += scale*stbtt_GetCodepointKernAdvance(&font, dos2utf(text[ch]),dos2utf(text[ch+1])); ++ch; } return ch; }
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; }
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(); }
Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) { ERR_FAIL_COND_V(!valid,Ref<DynamicFontAtSize>()); if (size_cache.has(p_size)) { return Ref<DynamicFontAtSize>( size_cache[p_size] ); } Ref<DynamicFontAtSize> dfas; dfas.instance(); dfas->font=Ref<DynamicFontData>( this ); size_cache[p_size]=dfas.ptr(); dfas->size=p_size; lock(); dfas->scale = stbtt_ScaleForPixelHeight(&info, p_size); unlock(); return dfas; }
// Bake a given set of ranges of chars int TTFFontAsset::BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in const GlyphRanges& ranges, // characters to bake BakedChar *chardata) { stbtt_fontinfo f; stbtt_InitFont(&f, data, offset); STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels int x = 1, y = 1; int bottom_y = 1; glyphMap.clear(); float scale = stbtt_ScaleForPixelHeight(&f, pixel_height); int bakedIdx = 0; for (GlyphRanges::const_iterator iter = ranges.begin(); iter != ranges.end(); ++iter) { const Range<int>& range = *iter; int numItemsInRange = range.high - range.low; for (int i = 0; i <= numItemsInRange; i++, bakedIdx++) { int unicodeCodepoint = i + range.low; glyphMap.insert(std::make_pair(unicodeCodepoint, bakedIdx)); int advance, lsb, x0,y0,x1,y1,gw,gh; int g = stbtt_FindGlyphIndex(&f, unicodeCodepoint); stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); gw = x1-x0; gh = y1-y0; if (x + gw + 1 >= pw) y = bottom_y, x = 1; // advance to next row if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row return -i; STBTT_assert(x+gw < pw); STBTT_assert(y+gh < ph); stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); chardata[bakedIdx].x0 = (stbtt_int16) x; chardata[bakedIdx].y0 = (stbtt_int16) y; chardata[bakedIdx].x1 = (stbtt_int16) (x + gw); chardata[bakedIdx].y1 = (stbtt_int16) (y + gh); chardata[bakedIdx].xadvance = scale * advance; chardata[bakedIdx].xoff = (float) x0; chardata[bakedIdx].yoff = (float) y0; x = x + gw + 2; if (y+gh+2 > bottom_y) bottom_y = y+gh+2; } } return bottom_y; }
JNIEXPORT jfloat JNICALL Java_com_badlogic_gdx_graphics_g2d_stbtt_StbTrueType_scaleForPixelHeight(JNIEnv* env, jclass clazz, jlong info, jfloat pixels) { //@line:53 return stbtt_ScaleForPixelHeight((stbtt_fontinfo*)info, pixels); }
bool Font::loadFromMemory(const unsigned char* buffer, unsigned int buffer_size) { if (!buffer || buffer_size == 0) return false; if (stbtt_InitFont(&m_info, buffer, 0) != 1) return false; m_scale = stbtt_ScaleForPixelHeight(&m_info, 16); return true; }
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; }
void GlFont::InitialiseFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h) { font_height_px = pixel_height; this->tex_w = tex_w; this->tex_h = tex_h; font_bitmap = new unsigned char[tex_w*tex_h]; const int offset = 0; stbtt_fontinfo f; if (!stbtt_InitFont(&f, ttf_buffer, offset)) { throw std::runtime_error("Unable to initialise font"); } float scale = stbtt_ScaleForPixelHeight(&f, pixel_height); STBTT_memset(font_bitmap, 0, tex_w*tex_h); int x = 1; int y = 1; int bottom_y = 1; // Generate bitmap and char indices for (int i=0; i < NUM_CHARS; ++i) { int advance, lsb, x0,y0,x1,y1,gw,gh; int g = stbtt_FindGlyphIndex(&f, FIRST_CHAR + i); stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); gw = x1-x0; gh = y1-y0; if (x + gw + 1 >= tex_w) y = bottom_y, x = 1; // advance to next row if (y + gh + 1 >= tex_h) // check if it fits vertically AFTER potentially moving to next row throw std::runtime_error("Unable to initialise font"); STBTT_assert(x+gw < tex_w); STBTT_assert(y+gh < tex_h); stbtt_MakeGlyphBitmap(&f, font_bitmap+x+y*tex_w, gw,gh,tex_w, scale,scale, g); // Adjust offset for edges of pixels chardata[i] = GlChar(tex_w,tex_h, x, y, gw, gh, scale*advance, x0 -0.5, -y0 -0.5); x = x + gw + 1; if (y+gh+1 > bottom_y) bottom_y = y+gh+1; } // Generate kern table for (int i=0; i < NUM_CHARS; ++i) { for (int j=0; j < NUM_CHARS; ++j) { kern_table[i*NUM_CHARS+j] = scale * stbtt_GetCodepointKernAdvance(&f,i,j); } } }
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; }
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; }
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; }
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; }
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; }
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; }
Purity::Font::Font(const std::string& fontFileName) : mFontFileName(fontFileName) { loadFont(); if (!stbtt_InitFont(&mFontInfo, mFontData.data(), 0)) { std::cerr << "Failed to initialize font" << std::endl; } int w, h; auto bitmap = stbtt_GetCodepointBitmap(&mFontInfo, 0, stbtt_ScaleForPixelHeight(&mFontInfo, 30), 'D', &w, &h, 0, 0); for (int j = 0; j < h; ++j) { for (int i = 0; i < w; ++i) putchar(" .:ioVM@"[bitmap[j * w + i] >> 5]); putchar('\n'); } }
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; }
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; }
void Font::setSize(int pixels) { m_scale = stbtt_ScaleForPixelHeight(&m_info, pixels); }
float font_width(struct font *font, float size, char *str) { return font_width_imp(font, stbtt_ScaleForPixelHeight(&font->info, size), str); }
void text_set_font(struct font *font, float size) { text_font = font; text_scale = stbtt_ScaleForPixelHeight(&font->info, size); }
int main(int argc, char **argv) { stbtt_fontinfo font; unsigned char *bitmap; int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 34807), s = (argc > 2 ? atoi(argv[2]) : 32); //debug(); // @TODO: why is minglui.ttc failing? fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb")); //fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/x/DroidSansMono.ttf", "rb")); { static stbtt_pack_context pc; static stbtt_packedchar cd[256]; static unsigned char atlas[1024*1024]; stbtt_PackBegin(&pc, atlas, 1024,1024,1024,1,NULL); stbtt_PackFontRange(&pc, ttf_buffer, 0, 32.0, 0, 256, cd); stbtt_PackEnd(&pc); } #if 0 stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits! stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); { stbtt_pack_context pc; stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 32, 95, pdata); stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 0xa0, 0x100-0xa0, pdata); stbtt_PackEnd(&pc); stbi_write_png("fonttest2.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); } { stbtt_pack_context pc; stbtt_pack_range pr[2]; stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); pr[0].chardata_for_range = pdata; pr[0].first_unicode_char_in_range = 32; pr[0].num_chars_in_range = 95; pr[0].font_size = 20.0f; pr[1].chardata_for_range = pdata+256; pr[1].first_unicode_char_in_range = 0xa0; pr[1].num_chars_in_range = 0x100 - 0xa0; pr[1].font_size = 20.0f; stbtt_PackSetOversampling(&pc, 2, 2); stbtt_PackFontRanges(&pc, ttf_buffer, 0, pr, 2); stbtt_PackEnd(&pc); stbi_write_png("fonttest3.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); } return 0; #endif stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, (float)s), c, &w, &h, 0,0); for (j=0; j < h; ++j) { for (i=0; i < w; ++i) putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); putchar('\n'); } return 0; }
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; }
stash::sth_glyph* stash::sth_font::get_glyph(unsigned int codepoint, short isize) { // Find code point and size. std::pair<unsigned int,int> key(codepoint, isize); if (glyphs.find( key ) != glyphs.end() ) return &glyphs.find( key )->second; // Could not find glyph, create it. int advance,lsb,x0,y0,x1,y1; int g = stbtt_FindGlyphIndex(&font, codepoint); float scale = stbtt_ScaleForPixelHeight(&font, isize/10.0f); stbtt_GetGlyphHMetrics(&font, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&font, g, scale,scale, &x0,&y0,&x1,&y1); int gw = x1-x0; int gh = y1-y0; // Find row where the glyph can be fit (vertically first, then horizontally) sth_row* br = 0; int rh = (gh+7) & ~7; for (size_t i = 0; i < rows->size() && !br; ++i) { if (rows->at(i).h == rh && rows->at(i).x+gw+1 <= tw) br = &rows->at(i); } // If no row found, add new. if (br == NULL) { short py = 0; // Check that there is enough space. if (rows->size()) { py = rows->back().y + rows->back().h+1; if (py+rh > th) return 0; } // Init and add row rows->push_back( sth_row(0,py,rh) ); br = &rows->back(); } // Init glyph. sth_glyph glyph; glyph.codepoint = codepoint; glyph.size = isize; glyph.x0 = br->x; glyph.y0 = br->y; glyph.x1 = glyph.x0+gw; glyph.y1 = glyph.y0+gh; glyph.xadv = scale * advance; glyph.xoff = (float)x0; glyph.yoff = (float)y0; // glyphs[ key ] = glyphs[ key ]; glyphs[ key ] = glyph; // Advance row location. br->x += gw+1; // Rasterize std::vector< unsigned char > bmp(gw*gh); if( bmp.size() ) { stbtt_MakeGlyphBitmap(&font, &bmp[0], gw,gh,gw, scale,scale, g); // Update texture glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexSubImage2D(GL_TEXTURE_2D, 0, glyph.x0,glyph.y0, gw,gh, GL_ALPHA,GL_UNSIGNED_BYTE,&bmp[0]); } return &glyphs[ key ]; }