new text measurement stuffs in working order!

This commit is contained in:
zetaPRIME 2017-03-15 19:17:50 -04:00
parent bca1adc6eb
commit 5960a56f60
4 changed files with 59 additions and 103 deletions

View File

@ -171,6 +171,6 @@ void OSK::DrawPreview(DrawLayerProxy& layer) {
void OSK::OnPreviewTap(DrawLayerProxy& layer) { void OSK::OnPreviewTap(DrawLayerProxy& layer) {
Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos; Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos;
auto& tc = PreviewTC(); auto& tc = PreviewTC();
handler->SetCursor(tc.font->GetCursorFromPoint(layer.rect, handler->GetPreviewText(), tpos + layer.rect.pos)); handler->SetCursor(tc.font->GetCursorFromPoint(layer.rect, handler->GetPreviewText(), tpos));
preview->Refresh(); preview->Refresh();
} }

View File

@ -87,111 +87,73 @@ float BitmapFont::DrawText(const Vector2& penStart, std::string& msg, float scal
} }
Vector2 BitmapFont::MeasureTo(std::string& msg, bool total, unsigned int end, float maxWidth) { Vector2 BitmapFont::MeasureTo(std::string& msg, bool total, unsigned int end, float maxWidth) {
auto len = msg.length(); if (total) {
if (end > len) end = len; Vector2 measure = Vector2::zero;
Vector2 pen = Vector2::zero; ForChar(msg, [&, this](auto& s){
Vector2 oPen = pen; if (s.i > end) return true;
float longest = 0; if (s.iline > 0) return false;
float wordlen = 0; measure.x = std::max(measure.x, s.lineWidth);
float plen = 0; measure.y += lineHeight;
return false;
}, maxWidth);
float space = Char(' ').advX; return measure;
for (unsigned int i = 0; i < len; i++) {
char& c = msg[i];
if (c == ' ' || c == '\n') {
bool lb = (c == '\n' || pen.x + wordlen > maxWidth);
oPen = pen;
if (lb) {
if (c == '\n') pen.x += space + wordlen; // previous word
longest = std::max(pen.x - space, longest);
pen.x = (c == ' ') ? (space + wordlen) : 0;
pen.y += lineHeight;
} else {
pen.x += space + wordlen;
} }
if (!total && i >= end) { Vector2 measure;
return Vector2(pen.x - (wordlen - plen) - space, pen.y); bool found = false;
ForChar(msg, [&, this, total, end](auto& s){
measure = Vector2(s.lineAcc + s.cc->advX, lineHeight * s.lineNum);
if (s.i == end-1) {
found = true;
if (s.i == s.lineEnd) measure = Vector2(0, lineHeight * (s.lineNum + 1)); // linebreak == next line
return true;
} }
wordlen = plen = 0; return false;
} else { }, maxWidth);
float adv = Char(c).advX;
wordlen += adv;
if (i < end) plen += adv;
}
}
longest = std::max(pen.x - space, longest);
if (pen.x + space + wordlen > maxWidth) { if (!found) { // catch newline-at-end
pen.x = wordlen; measure.x = 0;
pen.y += lineHeight; measure.y += lineHeight;
} else {
pen.x += wordlen + space;
}
longest = std::max(pen.x - space, longest); // do I need two of these?
if (!total) {
return Vector2(pen.x - (wordlen - plen) - space, pen.y); // return cursor position
} }
return Vector2(longest, pen.y + lineHeight); // total size return measure;
} }
unsigned int BitmapFont::PointToIndex(std::string& msg, Vector2 pt, float maxWidth) { unsigned int BitmapFont::PointToIndex(std::string& msg, Vector2 pt, float maxWidth) {
//pt -= Vector2(padX, 0*padY);
if (pt.y < 0) return 0; if (pt.y < 0) return 0;
auto len = msg.length(); unsigned int tl = std::floor(pt.y / lineHeight);
unsigned int line = 0; unsigned int idx;
unsigned int tLine = std::max(0.0f, std::floor(pt.y / lineHeight));
unsigned int le = 0; // line end ForChar(msg, [&, this, pt, tl](auto& s){
unsigned int ti = 4294967295; // target index if (s.lineNum < tl) return false; // skip
if (s.lineNum > tl) { // huh.
Vector2 pen = Vector2::zero; return true;
float wordlen = 0; }
if (s.i == s.lineEnd) {
float space = Char(' ').advX; if (s.i == s.lineStart) { // if blank line...
idx = s.i;
for (unsigned int i = 0; i < len; i++) { return true;
char& c = msg[i]; }
if (c == ' ' || c == '\n') { return false; // skip newlines on non-blank lines
// linebreak on newline or wrap needed
bool lb = (c == '\n' || pen.x + space + wordlen > maxWidth);
if (lb) {
if (c == '\n') le = i; // not wrapped
if (line == tLine) return std::min(le, ti);
pen.x = (c == ' ') ? wordlen : 0;
line++;
} else {
pen.x += wordlen + space;
if (line == tLine && ti == 4294967295 && pen.x - space*0.5f >= pt.x) ti = i;
le = i;
} }
wordlen = 0; // HERP DERP. if ((s.iline == 0 || pt.x >= s.lineAcc) && pt.x < s.lineAcc + s.cc->advX) {
} else { idx = s.i;
float cw = Char(c).advX; if (pt.x > s.lineAcc + s.cc->advX * 0.5f) idx++;
wordlen += cw; return true;
if (line == tLine && ti == 4294967295 && pen.x + wordlen - cw*0.5f >= pt.x) ti = i;
}
}
// oh right, process last word
if (pen.x + space + wordlen > maxWidth) {
if (line == tLine) return std::min(le, ti);
pen.x = wordlen;
line++;
} else {
le = len;
} }
if (line == tLine) return std::min(le, ti); idx = s.i+1;
return false;
}, maxWidth);
return len; return idx;
} }
void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopState&)> func, float maxWidth) { void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopState&)> func, float maxWidth) {
@ -201,6 +163,7 @@ void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopStat
float width; float width;
}; };
unsigned int len = msg.length();
float space = Char(' ').advX; float space = Char(' ').advX;
std::vector<LineStat> lines; std::vector<LineStat> lines;
@ -209,7 +172,6 @@ void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopStat
LineStat cl = {0, 0, 0}; LineStat cl = {0, 0, 0};
float ww = 0; float ww = 0;
unsigned int ws = 0; unsigned int ws = 0;
unsigned int len = msg.length();
for (unsigned int i = 0; i <= len; i++) { for (unsigned int i = 0; i <= len; i++) {
char c = (i == len) ? '\n' : msg[i]; char c = (i == len) ? '\n' : msg[i];
char pc = (i == 0) ? '\n' : msg[i-1]; char pc = (i == 0) ? '\n' : msg[i-1];
@ -262,9 +224,9 @@ void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopStat
state.lineAcc = 0; state.lineAcc = 0;
state.c = '\n'; state.c = '\n';
for (unsigned int i = cl.start; i < cl.end; i++) { for (unsigned int i = cl.start; i <= cl.end; i++) {
char pc = state.c; char pc = state.c;
state.c = msg[i]; state.c = (i >= len) ? '\n' : msg[i];
state.cc = &(Char(state.c)); state.cc = &(Char(state.c));
state.i = i; state.i = i;

View File

@ -34,7 +34,7 @@ void FontBMF::Print(Vector2 position, std::string& text, float scale, Color colo
Vector2 uvScale = Vector2::one / font->txMain->txSize; Vector2 uvScale = Vector2::one / font->txMain->txSize;
Vector2 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/); Vector2 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/);
font->ForChar(text, [&, this, ppen, justification, qn, scale, uvScale](auto& s){ font->ForChar(text, [&, this, ppen, justification, qn, scale, uvScale](auto& s){
if (s.c == ' ') return false; // skip spaces if (s.c == ' ' || s.c == '\n') return false; // skip spaces/newlines
Vector2 pen = (ppen + Vector2(s.lineAcc - s.lineWidth * justification.x, font->lineHeight * ((float)s.lineNum - (float)s.numLines * justification.y))) * scale; Vector2 pen = (ppen + Vector2(s.lineAcc - s.lineWidth * justification.x, font->lineHeight * ((float)s.lineNum - (float)s.numLines * justification.y))) * scale;
auto& ci = *s.cc; auto& ci = *s.cc;
VRect crect(ci.imgX, ci.imgY, ci.width, ci.height); VRect crect(ci.imgX, ci.imgY, ci.width, ci.height);
@ -64,7 +64,7 @@ void FontBMF::Print(VRect rect, std::string& text, float scale, Color color, Vec
Vector2 uvScale = Vector2::one / font->txMain->txSize; Vector2 uvScale = Vector2::one / font->txMain->txSize;
Vector2 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/); Vector2 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/);
font->ForChar(text, [&, this, ppen, justification, qn, scale, uvScale](auto& s){ font->ForChar(text, [&, this, ppen, justification, qn, scale, uvScale](auto& s){
if (s.c == ' ') return false; // skip spaces if (s.c == ' ' || s.c == '\n') return false; // skip spaces/newlines
Vector2 pen = (ppen + Vector2(s.lineAcc - s.lineWidth * justification.x, font->lineHeight * ((float)s.lineNum - (float)s.numLines * justification.y))) * scale; Vector2 pen = (ppen + Vector2(s.lineAcc - s.lineWidth * justification.x, font->lineHeight * ((float)s.lineNum - (float)s.numLines * justification.y))) * scale;
auto& ci = *s.cc; auto& ci = *s.cc;
VRect crect(ci.imgX, ci.imgY, ci.width, ci.height); VRect crect(ci.imgX, ci.imgY, ci.width, ci.height);

View File

@ -7,13 +7,7 @@ roadmap to first release, in no particular order {
- make backspace and enter actually do something - make backspace and enter actually do something
- abstract osk input actions into a separate object/class heirarchy - abstract osk input actions into a separate object/class heirarchy
- preview where applicable - preview where applicable
fix desync between cursor position, tap-cursor and display when a single word overflows a line
(cursor doesn't wrap until the next word!?)
fix font glyph padding to eliminate slight "crosstalk" in bordered variants fix font glyph padding to eliminate slight "crosstalk" in bordered variants
... reimplement as a per-character lambda-"loop" {
status object with stuff
precalculate line stats, then loop through each
}
polish! polish!
InputManager::OpenKeyboard InputManager::OpenKeyboard
} }