GLfloat QueryXOffsets( const CodePoint* cps, GLsizei size, std::vector<GLfloat>& x_offsets ) const { if(size <= 0) return 0.0f; x_offsets.resize(size); float scale = _tt_font.ScaleForPixelHeight(_font_resolution); scale /= _font_resolution; aux::STBTTFontGlyph g = _tt_font.GetGlyph(cps[0]); GLfloat sum = g.LeftBearing()*scale; x_offsets[0] = sum; GLsizei i = 0; while(++i != size) { sum += g.Width()*scale; aux::STBTTFontGlyph pg = g; g = _tt_font.GetGlyph(cps[i]); sum += KernAdvance(pg, g)*scale; x_offsets[i] = sum; } return sum + g.Width()*scale; }
OGLPLUS_LIB_FUNC float STBTTFont2D::Width( std::size_t size_in_pixels, const Layout& layout ) const { float scale = ScaleForPixelHeight(float(size_in_pixels)); float width = 0.0f; for(auto i=layout.begin(), p=i, e=layout.end(); i!=e; p = i, ++i) { if(p != i) width += KernAdvance(*p, *i); width += i->Width(); } return width*scale; }
OGLPLUS_LIB_FUNC void STBTTFont2D::Render( std::size_t size_in_pixels, const STBTTFont2D::Layout& layout, unsigned char* buffer_start, const std::size_t buffer_width, const std::size_t buffer_height, const int xposition, const int yposition ) const { if(int(buffer_height) < yposition) return; if(int(size_in_pixels) <= -yposition) return; std::vector<unsigned char> tmp_buffer; int tmp_height = int(size_in_pixels); int tmp_width = 0; float scale = ScaleForPixelHeight(float(size_in_pixels)); float xoffset = 0.0f; for(auto i=layout.begin(), p=i, e=layout.end(); i!=e; ++i) { const int xo = int(std::floor(xoffset))+xposition; const float advance = i->Width()*scale; int width_in_pixels = int(std::ceil(advance)); if(xo >= int(buffer_width)) { break; } if(xo+width_in_pixels < 0) { xoffset += advance; continue; } if(tmp_width < width_in_pixels) { tmp_width = width_in_pixels; tmp_buffer.resize(tmp_width*tmp_height); } std::fill(tmp_buffer.begin(), tmp_buffer.end(), 0x00); if(p != i) xoffset += KernAdvance(*p, *i)*scale; const float xshift = xoffset - std::floor(xoffset); int x0, y0, x1, y1; i->GetBitmapBoxSubpixel( scale, scale, xshift, 0, x0, y0, x1, y1 ); const float yshift = std::floor((i->Ascent()*scale+y0)); ::stbtt_MakeGlyphBitmapSubpixel( &_font, tmp_buffer.data(), tmp_width, tmp_height, tmp_width, scale, scale, xshift, yshift, i->_index ); const int yo = yposition; int gb = xo<0?-xo:0; int gw = int(gb+1+(x1-x0)); if(gw > tmp_width) gw = tmp_width; if(gw > int(buffer_width-xo)) gw = int(buffer_width-xo); int gy = (std::floor(yshift)); if(gy < -yo) gy = -yo; int gh = tmp_height; if(gh > int(buffer_height-yo)) gh = int(buffer_height-yo); while(gy < gh) { int gx = gb; while(gx < gw) { int si = gy*tmp_width+gx; unsigned src = tmp_buffer[si]; if(src != 0) { int di = (gy+yo)*buffer_width+gx+xo+x0; unsigned dst = buffer_start[di]+src; if(dst > 0xFF) dst = 0xFF; buffer_start[di] = dst & 0xFF; } ++gx; } ++gy; } p = i; xoffset += advance; } }