glyph appearance and color

This commit is contained in:
jrkb 2023-04-19 16:52:56 +02:00
parent c37609f3f7
commit 2f506000ab

View file

@ -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){