inline GLint BitmapGlyphCellOfCP( const BitmapGlyphRenderingBase& parent, CodePoint code_point ) { assert(BitmapGlyphGlyphsPerPage(parent) != 0); assert(BitmapGlyphGlyphsPerPage(parent) % 4 == 0); return code_point % BitmapGlyphGlyphsPerPage(parent); }
void _do_load_pages( const Element* elem, GLsizei size ) { _page_storage.Bind(); // go through the list of code-points for(GLsizei i=0; i!=size; ++i) { // get the page number for the glyph GLint page = elem[i]; // check if the page is active if(!_pager.UsePage(page)) { // if not let the pager find // a frame for the new page auto frame = _pager.FindFrame(); // load the bitmap image unsigned glyphs_per_page = BitmapGlyphGlyphsPerPage(_parent); std::vector<unsigned char> bmp(_tex_side*_tex_side); std::vector<GLfloat> metrics(glyphs_per_page*12); _do_make_page_bitmap_and_metric( page, bmp.data(), metrics.data() ); _page_storage.LoadPage( frame, images::Image( _tex_side, _tex_side, 1, 1, bmp.data(), PixelDataFormat::Red, PixelDataInternalFormat::R8 ), metrics ); // tell the pager that the page // is successfully loaded in the frame _pager.SwapPageIn(frame, page); } } }
std::vector<GLfloat> _make_page_metric(GLint page) { unsigned glyphs_per_page = BitmapGlyphGlyphsPerPage(_parent); std::vector<GLfloat> metrics(glyphs_per_page*12); // // x - logical rectangle left bearing // y - logical rectangle right bearing // z - logical rectangle ascent // w - logical rectangle descent // // x - ink rectangle left bearing // y - ink rectangle right bearing // z - ink rectangle ascent // w - ink rectangle descent // // x - Glyph origin x in normalized texture space // y - Glyph origin y in normalized texture space // z - Glyph width in normalized texture space // w - Glyph height in normalized texture space _do_make_page_bitmap_and_metric(page, nullptr, metrics.data()); return metrics; }
void _do_make_page_bitmap_and_metric( GLint page, unsigned char* bmp_data, float* metric ) const { float scale = _tt_font.ScaleForPixelHeight(_font_resolution); const GLuint px = _font_resolution; const GLuint ts = _tex_side; const float inv_px = 1.0f/float(px); const float inv_ts = 1.0f/float(ts); std::vector<unsigned char> tmp[2]; tmp[0].resize(px*px, 0x00); tmp[1].resize(px*px, 0x00); unsigned glyphs_per_page = BitmapGlyphGlyphsPerPage(_parent); int xoffs = 0, oldxoffs = 0; int yoffs = 0; int row_height = 0; int x0, y0, x1, y1, lb, width, asc, dsc, lg; for(unsigned g=0; g!=glyphs_per_page; ++g) { int code_point = glyphs_per_page*page+g; auto glyph = _tt_font.GetGlyph(code_point); if(std::isspace(code_point)) tmp[g%2]=std::vector<unsigned char>(px*px,0x00); glyph.MakeBitmap(tmp[g%2].data(), px, px, px, scale); // if this glyph is not the same as the previous if((g == 0) || (tmp[0] != tmp[1])) { glyph.GetBitmapBox(x0, y0, x1, y1); glyph.GetVMetrics(asc, dsc, lg); glyph.GetHMetrics(lb, width); int advance = int((x1-x0)*scale)+2; int glyph_height = int((y1-y0)*scale)+2; if(row_height < glyph_height) row_height = glyph_height; if(xoffs+advance >= int(ts)) { xoffs = 0; yoffs += row_height; row_height = 0; } if(bmp_data) { glyph.MakeBitmap( bmp_data+ts*yoffs+xoffs, advance, px, ts, scale ); } oldxoffs = xoffs; xoffs += advance; } if(metric) { float* p = metric+12*g; // logical rectangle metrics p[ 0] = lb*scale*inv_px; p[ 1] = (lb+width)*scale*inv_px; p[ 2] = asc*scale*inv_px; p[ 3] = -dsc*scale*inv_px; // ink rectangle metrics p[ 4] = x0*scale*inv_px; p[ 5] = x1*scale*inv_px; p[ 6] =-y0*scale*inv_px; p[ 7] = y1*scale*inv_px; // texture-space rectangle p[ 8] = (oldxoffs)*inv_ts; p[ 9] = (yoffs-y0*scale)*inv_ts; p[10] = ((x1-x0)*scale+1)*inv_ts; p[11] = ((y0-y1)*scale+1)*inv_ts; } } // TODO: hint that only the upper part of the image is actually // used + InvalidateTexImage // or increase the px value to get better resolution }