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;
ForChar(msg, [&, this](auto& s){
if (s.i > end) return true;
if (s.iline > 0) return false;
measure.x = std::max(measure.x, s.lineWidth);
measure.y += lineHeight;
return false;
}, maxWidth);
return measure;
}
Vector2 pen = Vector2::zero; Vector2 measure;
Vector2 oPen = pen; bool found = false;
float longest = 0;
float wordlen = 0;
float plen = 0;
float space = Char(' ').advX; ForChar(msg, [&, this, total, end](auto& s){
measure = Vector2(s.lineAcc + s.cc->advX, lineHeight * s.lineNum);
for (unsigned int i = 0; i < len; i++) { if (s.i == end-1) {
char& c = msg[i]; found = true;
if (c == ' ' || c == '\n') { if (s.i == s.lineEnd) measure = Vector2(0, lineHeight * (s.lineNum + 1)); // linebreak == next line
bool lb = (c == '\n' || pen.x + wordlen > maxWidth); return true;
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) {
return Vector2(pen.x - (wordlen - plen) - space, pen.y);
}
wordlen = plen = 0;
} else {
float adv = Char(c).advX;
wordlen += adv;
if (i < end) plen += adv;
} }
}
longest = std::max(pen.x - space, longest); return false;
}, maxWidth);
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;
float space = Char(' ').advX;
for (unsigned int i = 0; i < len; i++) {
char& c = msg[i];
if (c == ' ' || c == '\n') {
// 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.
} else {
float cw = Char(c).advX;
wordlen += cw;
if (line == tLine && ti == 4294967295 && pen.x + wordlen - cw*0.5f >= pt.x) ti = i;
} }
} if (s.i == s.lineEnd) {
// oh right, process last word if (s.i == s.lineStart) { // if blank line...
if (pen.x + space + wordlen > maxWidth) { idx = s.i;
if (line == tLine) return std::min(le, ti); return true;
pen.x = wordlen; }
line++; return false; // skip newlines on non-blank lines
} else { }
le = len;
} if ((s.iline == 0 || pt.x >= s.lineAcc) && pt.x < s.lineAcc + s.cc->advX) {
idx = s.i;
if (pt.x > s.lineAcc + s.cc->advX * 0.5f) idx++;
return true;
}
idx = s.i+1;
return false;
}, maxWidth);
if (line == tLine) return std::min(le, ti); return idx;
return len;
} }
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
} }