glyph appearance and color
This commit is contained in:
parent
c37609f3f7
commit
2f506000ab
1 changed files with 125 additions and 83 deletions
|
@ -143,6 +143,12 @@ struct GlyphIdentity {
|
|||
return this->charcode == other.charcode && this->coords == other.coords;
|
||||
}
|
||||
};
|
||||
|
||||
struct GlyphAppearance {
|
||||
uint32_t charcode;
|
||||
glm::vec4 color;
|
||||
float fontSize_px;
|
||||
};
|
||||
}
|
||||
// create hash for GlyphIdentity, so we can use it in our unordered_map as key
|
||||
namespace std {
|
||||
|
@ -919,6 +925,7 @@ class Font {
|
|||
}
|
||||
|
||||
void collectBoundingBoxes(const std::vector <GlyphIdentity> & variationText,
|
||||
const std::vector <GlyphAppearance> & variationTextAppearance,
|
||||
BoundingBox & boundingBox,
|
||||
std::vector <BoundingBox> & boundingBoxes,
|
||||
float & advanceY,
|
||||
|
@ -932,18 +939,21 @@ class Font {
|
|||
float minY = FLT_MAX;
|
||||
float maxX = -FLT_MAX;
|
||||
float maxY = -FLT_MAX;
|
||||
int i = 0;
|
||||
for(const GlyphIdentity & glyphIdentity : variationText){
|
||||
const GlyphAppearance & glyphAppearance = variationTextAppearance[i];
|
||||
if(glyphIdentity.charcode == '\0'){
|
||||
break;
|
||||
}
|
||||
float letterFontSize_px = fontSize_px; // can be individual
|
||||
float letterFontSize_px = glyphAppearance.fontSize_px; // can be individual
|
||||
const uint32_t & charcode = glyphIdentity.charcode;
|
||||
|
||||
if(charcode == '\r'){
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(charcode == '\n' || charcode == 'n'){
|
||||
if(charcode == '\n'){
|
||||
advanceX = 0;
|
||||
advanceY += getLineHeight(fontSize_px);
|
||||
if(!vFlip){
|
||||
|
@ -952,6 +962,7 @@ class Font {
|
|||
if(hinting){
|
||||
advanceY = std::round(advanceY);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -963,7 +974,7 @@ class Font {
|
|||
FT_Vector kerning;
|
||||
FT_Error error = FT_Get_Kerning(face, previous, glyph.index, kerningMode, &kerning);
|
||||
if(!error){
|
||||
advanceX += ((float)kerning.x * fontSize_px) / emSize * worldSize;
|
||||
advanceX += ((float)kerning.x * letterFontSize_px) / emSize * worldSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1009,6 +1020,7 @@ class Font {
|
|||
|
||||
advanceX += ((float)glyph.advance * letterFontSize_px) / emSize * worldSize;
|
||||
previous = glyph.index;
|
||||
i++;
|
||||
}
|
||||
boundingBox.p0 = glm::vec4(minX, minY, 0, 1);
|
||||
boundingBox.p1 = glm::vec4(maxX, minY, 0, 1);
|
||||
|
@ -1024,114 +1036,144 @@ class Font {
|
|||
}
|
||||
|
||||
void collectVerticesAndIndices(const ofNode & node,
|
||||
const std::vector <GlyphAppearance> & variationTextAppearance,
|
||||
std::vector <BoundingBox> & boundingBoxes,
|
||||
std::vector <BufferVertex> & vertices,
|
||||
std::vector <int32_t> & indices,
|
||||
const glm::vec4 & color = glm::vec4(1),
|
||||
const float fontSize_px = 42){
|
||||
std::vector <int32_t> & indices){
|
||||
|
||||
int i = 0;
|
||||
for(BoundingBox & bb : boundingBoxes){
|
||||
bool hasGoodCharacter = false;
|
||||
while(!hasGoodCharacter && i < variationTextAppearance.size() - 1){
|
||||
if(variationTextAppearance[i].charcode == '\0'
|
||||
|| variationTextAppearance[i].charcode == '\r'
|
||||
|| variationTextAppearance[i].charcode == '\n'){
|
||||
i++;
|
||||
}else{
|
||||
hasGoodCharacter = true;
|
||||
}
|
||||
}
|
||||
|
||||
bb.multiply(node.getGlobalTransformMatrix());
|
||||
|
||||
int32_t base = static_cast <int32_t>(vertices.size());
|
||||
vertices.push_back(BufferVertex{bb.p0.x, bb.p0.y, bb.u0, bb.v0, bb.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{bb.p1.x, bb.p1.y, bb.u1, bb.v0, bb.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{bb.p2.x, bb.p2.y, bb.u1, bb.v1, bb.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{bb.p3.x, bb.p3.y, bb.u0, bb.v1, bb.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
const glm::vec4 & color = variationTextAppearance[i].color;
|
||||
vertices.push_back(BufferVertex{bb.p0.x, bb.p0.y, bb.u0, bb.v0, bb.bufferIndex,
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a});
|
||||
vertices.push_back(BufferVertex{bb.p1.x, bb.p1.y, bb.u1, bb.v0, bb.bufferIndex,
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a});
|
||||
vertices.push_back(BufferVertex{bb.p2.x, bb.p2.y, bb.u1, bb.v1, bb.bufferIndex,
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a});
|
||||
vertices.push_back(BufferVertex{bb.p3.x, bb.p3.y, bb.u0, bb.v1, bb.bufferIndex,
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a});
|
||||
|
||||
indices.insert(indices.end(), {base, base + 1, base + 2, base + 2, base + 3, base});
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void collectVerticesAndIndices(const ofNode & node,
|
||||
const std::vector <GlyphIdentity> & variationText,
|
||||
std::vector <BufferVertex> & vertices,
|
||||
std::vector <int32_t> & indices,
|
||||
const glm::vec4 & color = glm::vec4(1),
|
||||
const bool vFlip = false,
|
||||
const float fontSize_px = 42){
|
||||
float advanceX = 0;
|
||||
float advanceY = 0;
|
||||
// NOTE: following only exists for nostalgic reason
|
||||
//
|
||||
//void collectVerticesAndIndices(const ofNode & node,
|
||||
//const std::vector <GlyphIdentity> & variationText,
|
||||
//std::vector <BufferVertex> & vertices,
|
||||
//std::vector <int32_t> & indices,
|
||||
//const glm::vec4 & color = glm::vec4(1),
|
||||
//const bool vFlip = false,
|
||||
//const float fontSize_px = 42){
|
||||
//float advanceX = 0;
|
||||
//float advanceY = 0;
|
||||
|
||||
FT_UInt previous = 0;
|
||||
for(const GlyphIdentity & glyphIdentity : variationText){
|
||||
if(glyphIdentity.charcode == '\0'){
|
||||
break;
|
||||
}
|
||||
float letterFontSize_px = fontSize_px; // can be individual
|
||||
const uint32_t & charcode = glyphIdentity.charcode;
|
||||
//FT_UInt previous = 0;
|
||||
//for(const GlyphIdentity & glyphIdentity : variationText){
|
||||
//if(glyphIdentity.charcode == '\0'){
|
||||
//break;
|
||||
//}
|
||||
//float letterFontSize_px = fontSize_px; // can be individual
|
||||
//const uint32_t & charcode = glyphIdentity.charcode;
|
||||
|
||||
if(charcode == '\r'){
|
||||
continue;
|
||||
}
|
||||
//if(charcode == '\r'){
|
||||
//continue;
|
||||
//}
|
||||
|
||||
if(charcode == '\n' || charcode == 'n'){
|
||||
advanceX = 0;
|
||||
advanceY += ((float)face->height * fontSize_px) / (float)face->units_per_EM * worldSize;
|
||||
if(!vFlip){
|
||||
advanceY *= -1;
|
||||
}
|
||||
if(hinting){
|
||||
advanceY = std::round(advanceY);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//if(charcode == '\n' || charcode == 'n'){
|
||||
//advanceX = 0;
|
||||
//advanceY += ((float)face->height * fontSize_px) / (float)face->units_per_EM * worldSize;
|
||||
//if(!vFlip){
|
||||
//advanceY *= -1;
|
||||
//}
|
||||
//if(hinting){
|
||||
//advanceY = std::round(advanceY);
|
||||
//}
|
||||
//continue;
|
||||
//}
|
||||
|
||||
auto glyphIt = glyphs.find(glyphIdentity);
|
||||
Glyph & glyph = (glyphIt == glyphs.end()) ? glyphs.begin()->second : glyphIt->second; // in case we have no glyph, draw first one?
|
||||
// NOTE: should we do this?
|
||||
//auto glyphIt = glyphs.find(glyphIdentity);
|
||||
//Glyph & glyph = (glyphIt == glyphs.end()) ? glyphs.begin()->second : glyphIt->second; // in case we have no glyph, draw first one?
|
||||
//// NOTE: should we do this?
|
||||
|
||||
if(previous != 0 && glyph.index != 0){
|
||||
FT_Vector kerning;
|
||||
FT_Error error = FT_Get_Kerning(face, previous, glyph.index, kerningMode, &kerning);
|
||||
if(!error){
|
||||
advanceX += ((float)kerning.x * fontSize_px) / emSize * worldSize;
|
||||
}
|
||||
}
|
||||
//if(previous != 0 && glyph.index != 0){
|
||||
//FT_Vector kerning;
|
||||
//FT_Error error = FT_Get_Kerning(face, previous, glyph.index, kerningMode, &kerning);
|
||||
//if(!error){
|
||||
//advanceX += ((float)kerning.x * fontSize_px) / emSize * worldSize;
|
||||
//}
|
||||
//}
|
||||
|
||||
// Do not emit quad for empty glyphs (whitespace).
|
||||
if(glyph.curveCount){
|
||||
FT_Pos d = (FT_Pos)(emSize * dilation);
|
||||
//// Do not emit quad for empty glyphs (whitespace).
|
||||
//if(glyph.curveCount){
|
||||
//FT_Pos d = (FT_Pos)(emSize * dilation);
|
||||
|
||||
float u0 = (float)(glyph.bearingX - d) / emSize;
|
||||
float v0 = (float)(glyph.bearingY - glyph.height - d) / emSize;
|
||||
float u1 = (float)(glyph.bearingX + glyph.width + d) / emSize;
|
||||
float v1 = (float)(glyph.bearingY + d) / emSize;
|
||||
//float u0 = (float)(glyph.bearingX - d) / emSize;
|
||||
//float v0 = (float)(glyph.bearingY - glyph.height - d) / emSize;
|
||||
//float u1 = (float)(glyph.bearingX + glyph.width + d) / emSize;
|
||||
//float v1 = (float)(glyph.bearingY + d) / emSize;
|
||||
|
||||
float x0 = advanceX + u0 * worldSize * letterFontSize_px;
|
||||
float y0 = v0 * worldSize * letterFontSize_px;
|
||||
float x1 = advanceX + u1 * worldSize * letterFontSize_px;
|
||||
float y1 = v1 * worldSize * letterFontSize_px;
|
||||
//float x0 = advanceX + u0 * worldSize * letterFontSize_px;
|
||||
//float y0 = v0 * worldSize * letterFontSize_px;
|
||||
//float x1 = advanceX + u1 * worldSize * letterFontSize_px;
|
||||
//float y1 = v1 * worldSize * letterFontSize_px;
|
||||
|
||||
if(vFlip){
|
||||
float _v = v0;
|
||||
v0 = v1;
|
||||
v1 = _v;
|
||||
//if(vFlip){
|
||||
//float _v = v0;
|
||||
//v0 = v1;
|
||||
//v1 = _v;
|
||||
|
||||
y0 = -v0 * worldSize * letterFontSize_px;
|
||||
y1 = -v1 * worldSize * letterFontSize_px;
|
||||
}
|
||||
//y0 = -v0 * worldSize * letterFontSize_px;
|
||||
//y1 = -v1 * worldSize * letterFontSize_px;
|
||||
//}
|
||||
|
||||
glm::vec4 p0 = node.getGlobalTransformMatrix() * glm::vec4(x0, y0 + advanceY, 0, 1);
|
||||
glm::vec4 p1 = node.getGlobalTransformMatrix() * glm::vec4(x1, y0 + advanceY, 0, 1);
|
||||
glm::vec4 p2 = node.getGlobalTransformMatrix() * glm::vec4(x1, y1 + advanceY, 0, 1);
|
||||
glm::vec4 p3 = node.getGlobalTransformMatrix() * glm::vec4(x0, y1 + advanceY, 0, 1);
|
||||
//glm::vec4 p0 = node.getGlobalTransformMatrix() * glm::vec4(x0, y0 + advanceY, 0, 1);
|
||||
//glm::vec4 p1 = node.getGlobalTransformMatrix() * glm::vec4(x1, y0 + advanceY, 0, 1);
|
||||
//glm::vec4 p2 = node.getGlobalTransformMatrix() * glm::vec4(x1, y1 + advanceY, 0, 1);
|
||||
//glm::vec4 p3 = node.getGlobalTransformMatrix() * glm::vec4(x0, y1 + advanceY, 0, 1);
|
||||
|
||||
int32_t base = static_cast <int32_t>(vertices.size());
|
||||
vertices.push_back(BufferVertex{p0.x, p0.y, u0, v0, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{p1.x, p1.y, u1, v0, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{p2.x, p2.y, u1, v1, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
vertices.push_back(BufferVertex{p3.x, p3.y, u0, v1, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
//int32_t base = static_cast <int32_t>(vertices.size());
|
||||
//vertices.push_back(BufferVertex{p0.x, p0.y, u0, v0, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
//vertices.push_back(BufferVertex{p1.x, p1.y, u1, v0, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
//vertices.push_back(BufferVertex{p2.x, p2.y, u1, v1, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
//vertices.push_back(BufferVertex{p3.x, p3.y, u0, v1, glyph.bufferIndex, color.r, color.g, color.b, color.a});
|
||||
|
||||
indices.insert(indices.end(), {base, base + 1, base + 2, base + 2, base + 3, base});
|
||||
}
|
||||
//indices.insert(indices.end(), {base, base + 1, base + 2, base + 2, base + 3, base});
|
||||
//}
|
||||
|
||||
advanceX += ((float)glyph.advance * letterFontSize_px) / emSize * worldSize;
|
||||
previous = glyph.index;
|
||||
}
|
||||
}
|
||||
//advanceX += ((float)glyph.advance * letterFontSize_px) / emSize * worldSize;
|
||||
//previous = glyph.index;
|
||||
//}
|
||||
//}
|
||||
|
||||
void draw(const std::vector <BufferVertex> & vertices,
|
||||
const std::vector <int32_t> & indices){
|
||||
|
|
Loading…
Reference in a new issue