@ -45,7 +45,7 @@ TextRasterizer::~TextRasterizer() {
@@ -45,7 +45,7 @@ TextRasterizer::~TextRasterizer() {
FT_Done_FreeType ( lib ) ;
}
std : : unique_ptr < std : : pair < int , int > > TextRasterizer : : size ( const rasterizationRequest & request ) const {
std : : unique_ptr < sizeResponse > TextRasterizer : : size ( const rasterizationRequest & request ) const {
if ( ! request . availableWidth ) {
// window is likely minimized, so no output
return nullptr ;
@ -81,18 +81,20 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
@@ -81,18 +81,20 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
const hb_glyph_info_t * glyphInfo = hb_buffer_get_glyph_infos ( buffer , & glyphCount ) ;
const hb_glyph_position_t * glyphPos = hb_buffer_get_glyph_positions ( buffer , & glyphCount ) ;
std : : unique_ptr < rasterization Response> response = std : : make_unique < rasterization Response> ( ) ;
std : : unique_ptr < size Response> response = std : : make_unique < size Response> ( ) ;
// figure out width/height
int cx = 0 ;
int cy = 0 ;
int xmax = 0 ;
int y0max = 0 , y1max = 0 ;
int lines = 1 ;
//int y0max = 0;
int y1max = 0 ;
//int lines = 1;
response - > wrapped = false ;
int lineXStart = request . startX ;
int leftPadding = 0 ;
int wrapToX = 0 ;
//int leftPadding = 0;
//int wrapToX = 0;
int maxy0 = 0 ;
for ( unsigned int i = 0 ; i < glyphCount ; i + + ) {
if ( FT_Load_Glyph ( * face , glyphInfo [ i ] . codepoint , FT_LOAD_DEFAULT ) ) {
std : : cout < < " Could not load glyph " < < std : : endl ;
@ -108,12 +110,39 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
@@ -108,12 +110,39 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
// how much space does this character take
const float xa = static_cast < float > ( glyphPos [ i ] . x_advance ) / 64 ;
const float ya = static_cast < float > ( glyphPos [ i ] . y_advance ) / 64 ; //mostly 0s
const float yo = static_cast < float > ( glyphPos [ i ] . y_offset ) / 64 ;
int y0 = static_cast < int > ( floor ( yo + slot - > bitmap_top ) ) ;
//miny0 = std::min(y0, miny0);
maxy0 = std : : max ( y0 , maxy0 ) ;
// do we need to padding the texture to the left for any lines
if ( cx = = 0 ) {
if ( slot - > bitmap_left < 0 ) {
// figure out max amount of padding we need
leftPadding = std : : max ( leftPadding , - slot - > bitmap_left ) ;
response - > leftPadding = std : : max ( response - > leftPadding , - slot - > bitmap_left ) ;
}
}
// manual request to wrap (new line)
//std::cout << "char " << request.text[i] << " codepoint: " << glyphInfo[i].codepoint << std::endl;
if ( request . text [ i ] = = ' \n ' | | request . text [ i ] = = ' \r ' ) {
//std::cout << "new line|return" << std::endl;
response - > wrapped = true ;
if ( request . noWrap ) {
glyphCount = i ;
// we're done
std : : cout < < " TextRasterizer::rasterize - newline found no wrap is on " < < std : : endl ;
break ;
} else {
xmax = std : : max ( xmax , cx ) ;
cx = response - > wrapToX ;
cy - = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
response - > lines + + ;
lineXStart = response - > wrapToX ; // change where we start
// don't add this character
continue ;
}
}
@ -125,12 +154,12 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
@@ -125,12 +154,12 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
} else {
//std::cout << "multine text: [" << text << "] new line:" << cy << " x: " << (int)x << "+ cx:" << (int)cx << std::endl;
//std::cout << "line #" << lines << " starts at " << lineXStart << " ends at " << lineXStart + cx << std::endl;
xmax = request . availableWidth - wrapToX ; // the whole width of parent to the edge of windowWidth
xmax = request . availableWidth - response - > wrapToX ; // the whole width of parent to the edge of windowWidth
//std::cout << "new width: " << xmax << std::endl;
cx = wrapToX ; // wrapToX (was 0) (was -= xmax)
cx = response - > wrapToX ; // wrapToX (was 0) (was -= xmax)
cy - = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
lines + + ;
lineXStart = wrapToX ; // change where we start
response - > lines + + ;
lineXStart = response - > wrapToX ; // change where we start
}
}
@ -142,33 +171,43 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
@@ -142,33 +171,43 @@ std::unique_ptr<std::pair<int, int>> TextRasterizer::size(const rasterizationReq
// update glyph maxes
const FT_Bitmap ftBitmap = slot - > bitmap ;
const float yo = static_cast < float > ( glyphPos [ i ] . y_offset ) / 64 ;
int y0 = static_cast < int > ( floor ( yo + slot - > bitmap_top ) ) ;
//const float yo = static_cast<float>(glyphPos[i].y_offset) / 64;
//int y0 = static_cast<int>(floor(yo + slot->bitmap_top));
int y1 = y0 + static_cast < int > ( ftBitmap . rows ) ;
y0max = std : : max ( y0max , y0 ) ;
response - > y0max = std : : max ( response - > y0max , y0 ) ;
y1max = std : : max ( y1max , y1 ) ;
// track new max width
xmax = std : : max ( xmax , cx ) ;
}
if ( leftPadding ) {
xmax + = leftPadding ; // increase width;
if ( response - > leftPadding ) {
xmax + = response - > leftPadding ; // increase width;
}
// at least one line
cy - = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
response - > height = - cy ;
response - > width = xmax ;
//std::cout << "lines: " << lines << " wrapToX: " << wrapToX << " startX: " << x << " xmax: " << xmax << std::endl;
//std::cout << "y1max: " << y1max << " lines: " << lines << std::endl;
y1max * = lines ;
if ( response - > y0max ! = maxy0 ) {
std : : cout < < " TextRasterizer::size - resp.y0max: " < < response - > y0max < < " maxy0: " < < maxy0 < < std : : endl ;
}
//std::cout << "y1max: " << y1max << " lines: " << response->lines << std::endl;
int textureHeight = ( y1max - response - > y0max ) * response - > lines ;
//int textureHeight = y1max * response->lines;
//y1max *= response->lines;
//std::cout << "initial:" << (int)width << "x" << (int)height << std::endl;
if ( response - > height < y1max ) {
response - > height = y1max ;
if ( response - > height < textureHeight ) {
response - > height = textureHeight ;
//std::cout << "adjusted:" << (int)width << "x" << (int)height << std::endl;
}
response - > endingX = cx - request . sourceStartX ;
response - > endingY = cy + 2 + request . sourceStartY ;
// FIXME: how about endingX,Y?
return std : : make_unique < std : : pair < int , int > > ( std : : pair < int , int > ( response - > width , response - > height ) ) ;
//return std::make_unique<std::pair<int, int>>(std::pair<int, int>(response->width, response->height));
return response ;
}
# include <GL/glew.h>
@ -206,100 +245,12 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -206,100 +245,12 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
const hb_glyph_position_t * glyphPos = hb_buffer_get_glyph_positions ( buffer , & glyphCount ) ;
std : : unique_ptr < rasterizationResponse > response = std : : make_unique < rasterizationResponse > ( ) ;
std : : unique_ptr < sizeResponse > sizeResponse = this - > size ( request ) ;
// figure out width/height
int cx = 0 ;
int cy = 0 ;
int xmax = 0 ;
int y0max = 0 , y1max = 0 ;
int lines = 1 ;
response - > wrapped = false ;
int lineXStart = request . startX ;
int leftPadding = 0 ;
int wrapToX = 0 ;
for ( unsigned int i = 0 ; i < glyphCount ; i + + ) {
if ( FT_Load_Glyph ( * face , glyphInfo [ i ] . codepoint , FT_LOAD_DEFAULT ) ) {
std : : cout < < " Could not load glyph " < < std : : endl ;
return nullptr ;
}
const FT_GlyphSlot slot = ( * face ) - > glyph ;
if ( FT_Render_Glyph ( slot , FT_RENDER_MODE_NORMAL ) ) {
std : : cout < < " Could not render glyph " < < std : : endl ;
return nullptr ;
}
// how much space does this character take
const float xa = static_cast < float > ( glyphPos [ i ] . x_advance ) / 64 ;
const float ya = static_cast < float > ( glyphPos [ i ] . y_advance ) / 64 ; //mostly 0s
// do we need to padding the texture to the left for any lines
if ( cx = = 0 ) {
if ( slot - > bitmap_left < 0 ) {
// figure out max amount of padding we need
leftPadding = std : : max ( leftPadding , - slot - > bitmap_left ) ;
}
}
// wrap to next line on width
if ( ( cx + lineXStart ) - request . sourceStartX > = request . availableWidth ) {
response - > wrapped = true ;
if ( request . noWrap ) {
std : : cout < < " TextRasterizer::rasterize - we've hit wrap & noWrap at " < < cx < < " + " < < lineXStart < < " < " < < request . availableWidth < < std : : endl ;
// we can only fit partial of the last char
std : : cout < < " TextRasterizer::rasterize - truncating " < < glyphCount < < " char(s) to " < < i < < " char(s) " < < std : : endl ;
glyphCount = i ;
// we're done
break ;
} else {
//std::cout << "multine text: [" << text << "] new line:" << cy << " x: " << (int)x << "+ cx:" << (int)cx << std::endl;
//std::cout << "line #" << lines << " starts at " << lineXStart << " ends at " << lineXStart + cx << std::endl;
xmax = request . availableWidth - wrapToX ; // the whole width of parent to the edge of windowWidth
//std::cout << "new width: " << xmax << std::endl;
cx = wrapToX ; // wrapToX (was 0) (was -= xmax)
cy - = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
lines + + ;
lineXStart = wrapToX ; // change where we start
}
}
//std::cout << "glyph:" << xa << "x" << ya << std::endl;
// update glyph space allocation
cx + = xa ;
cy + = ya ; // is normal for y0 at bottom
// update glyph maxes
const FT_Bitmap ftBitmap = slot - > bitmap ;
const float yo = static_cast < float > ( glyphPos [ i ] . y_offset ) / 64 ;
int y0 = static_cast < int > ( floor ( yo + slot - > bitmap_top ) ) ;
int y1 = y0 + static_cast < int > ( ftBitmap . rows ) ;
y0max = std : : max ( y0max , y0 ) ;
y1max = std : : max ( y1max , y1 ) ;
// track new max width
xmax = std : : max ( xmax , cx ) ;
}
//std::cout << "TextRasterizer::rasterize - xmax exits loop at " << xmax << std::endl;
if ( leftPadding ) {
//std::cout << "TextRasterizer::rasterize - leftPadding " << leftPadding << std::endl;
xmax + = leftPadding ; // increase width;
}
// at least one line
cy - = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
//std::cout << "TextRasterizer::rasterize - initial width " << xmax << std::endl;
response - > width = xmax ;
response - > height = - cy ;
//std::cout << "lines: " << lines << " wrapToX: " << wrapToX << " startX: " << x << " xmax: " << xmax << std::endl;
//std::cout << "y1max: " << y1max << " lines: " << lines << std::endl;
y1max * = lines ;
//std::cout << "initial:" << (int)width << "x" << (int)height << std::endl;
if ( response - > height < y1max ) {
response - > height = y1max ;
//std::cout << "adjusted:" << (int)width << "x" << (int)height << std::endl;
}
response - > width = sizeResponse - > width ;
response - > height = sizeResponse - > height ;
//std::cout << "after adjust:" << (int)response->width << "x" << (int)response->height << " lines" << lines << std::endl;
// adjust sourceStart
//std::cout << "TextRasterizer::rasterize - adjust sourceStart: " << request.sourceStartX << "," << request.sourceStartY << std::endl;
response - > width - = request . sourceStartX ;
@ -324,9 +275,9 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -324,9 +275,9 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
}
// translation information
response - > x0 = - leftPadding ; // wrap to element start (wrapToX (0) or x)
response - > x0 = - sizeResponse - > leftPadding ; // wrap to element start (wrapToX (0) or x)
response - > y0 = 0 ;
response - > x1 = - leftPadding + response - > width ;
response - > x1 = - sizeResponse - > leftPadding + response - > width ;
response - > y1 = - response - > height ;
//std::cout << "xd: " << static_cast<int>(response->x1-response->x0) << " yd: " << static_cast<int>(response->y0-response->y1) << std::endl;
@ -345,8 +296,8 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -345,8 +296,8 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
// copy all glyphs into one single glyph
// still neds to start at X
cx = response - > wrapped ? request . startX : 0 ; // reset
cy = 0 ;
int cx = response - > wrapped ? request . startX : 0 ; // reset
int cy = 0 ;
//std::cout << "[" << request.text << "] wrapped? " << response->wrapped << " starting at: " << cx << std::endl;
//int miny0 = 99;
int maxy0 = 0 ;
@ -371,11 +322,26 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -371,11 +322,26 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
//miny0 = std::min(y0, miny0);
maxy0 = std : : max ( y0 , maxy0 ) ;
int bump = y0max - y0 ; // Y adjust for this glyph
int bump = sizeResponse - > y0max - y0 ; // Y adjust for this glyph
const float xa = static_cast < float > ( glyphPos [ i ] . x_advance ) / 64 ;
if ( request . text [ i ] = = ' \n ' | | request . text [ i ] = = ' \r ' ) {
//std::cout << "new line" << std::endl;
if ( request . noWrap ) {
// we're done
//std::cout << "TextRasterize::rasterize - noWrap on, ending" << std::endl;
break ;
} else {
cx = sizeResponse - > wrapToX ;
cy + = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
// no need to write new line char
continue ;
}
}
// if this char is too width for this line, advance to next line
if ( ! request . noWrap & & cx + xa > = request . availableWidth ) {
cx = wrapToX ;
cx = sizeResponse - > wrapToX ;
cy + = std : : ceil ( 1.2f * fontSize ) ; // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
//std::cout << "textWrap - cx reset to: " << cx << " cy is now: " << cy << std::endl;
}
@ -386,13 +352,20 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -386,13 +352,20 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
cx + = xa ;
continue ;
}
if ( cy < request . sourceStartY ) {
// skip ahead
// seems to just an optimization
//std::cout << "cy: " << cy << " < sourceStartY: " << request.sourceStartY << std::endl;
continue ;
}
//std::cout << "Writing " << request.text[i] << " to " << cx << ", " << cy << std::endl;
// place glyph bitmap data into texture
for ( unsigned int iy = 0 ; iy < ftBitmap . rows ; iy + + ) { // line by line
// source is 0 to (0:iy:rows)
// dest is cx+bl, (0:iy:rows)+(0:cy:height)+bump
//std::cout << "placing glyph row at " << (cx + slot->bitmap_left) << "x" << ((iy + cy) + bump) << std::endl;
unsigned int destPos = static_cast < unsigned int > ( cx - request . sourceStartX + leftPadding + slot - > bitmap_left ) + ( ( iy + static_cast < unsigned int > ( cy - request . sourceStartY ) ) + static_cast < unsigned int > ( bump ) ) * response - > textureWidth ;
unsigned int destPos = static_cast < unsigned int > ( cx - request . sourceStartX + sizeResponse - > leftPadding + slot - > bitmap_left ) + ( ( iy + static_cast < unsigned int > ( cy - request . sourceStartY ) ) + static_cast < unsigned int > ( bump ) ) * response - > textureWidth ;
if ( destPos > = size ) {
// we're done with this line
continue ;
@ -405,8 +378,9 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
@@ -405,8 +378,9 @@ std::unique_ptr<rasterizationResponse> TextRasterizer::rasterize(const rasteriza
continue ;
}
//std::cout << "putting:" << (int)src[ix] << " over " << (int)dest[ix] << std::endl;
if ( src [ ix ] & & src [ ix ] > dest [ ix ] ) {
dest [ ix ] = src [ ix ] ;
// probably could be or'd
if ( src [ ix ] & & src [ ix ] > dest [ ix ] ) {
dest [ ix ] = src [ ix ] ;
}
}
}