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) {
Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos;
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();
}

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) {
auto len = msg.length();
if (end > len) end = len;
if (total) {
Vector2 measure = Vector2::zero;
Vector2 pen = Vector2::zero;
Vector2 oPen = pen;
float longest = 0;
float wordlen = 0;
float plen = 0;
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);
float space = Char(' ').advX;
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;
return measure;
}
if (!total && i >= end) {
return Vector2(pen.x - (wordlen - plen) - space, pen.y);
Vector2 measure;
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;
} 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) {
pen.x = wordlen;
pen.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
if (!found) { // catch newline-at-end
measure.x = 0;
measure.y += lineHeight;
}
return Vector2(longest, pen.y + lineHeight); // total size
return measure;
}
unsigned int BitmapFont::PointToIndex(std::string& msg, Vector2 pt, float maxWidth) {
//pt -= Vector2(padX, 0*padY);
if (pt.y < 0) return 0;
auto len = msg.length();
unsigned int tl = std::floor(pt.y / lineHeight);
unsigned int line = 0;
unsigned int tLine = std::max(0.0f, std::floor(pt.y / lineHeight));
unsigned int idx;
unsigned int le = 0; // line end
unsigned int ti = 4294967295; // target index
Vector2 pen = Vector2::zero;
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;
ForChar(msg, [&, this, pt, tl](auto& s){
if (s.lineNum < tl) return false; // skip
if (s.lineNum > tl) { // huh.
return true;
}
if (s.i == s.lineEnd) {
if (s.i == s.lineStart) { // if blank line...
idx = s.i;
return true;
}
return false; // skip newlines on non-blank lines
}
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;
}
}
// 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 ((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;
}
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) {
@ -201,6 +163,7 @@ void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopStat
float width;
};
unsigned int len = msg.length();
float space = Char(' ').advX;
std::vector<LineStat> lines;
@ -209,7 +172,6 @@ void BitmapFont::ForChar(const std::string& msg, std::function<bool(CharLoopStat
LineStat cl = {0, 0, 0};
float ww = 0;
unsigned int ws = 0;
unsigned int len = msg.length();
for (unsigned int i = 0; i <= len; i++) {
char c = (i == len) ? '\n' : msg[i];
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.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;
state.c = msg[i];
state.c = (i >= len) ? '\n' : msg[i];
state.cc = &(Char(state.c));
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 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/);
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;
auto& ci = *s.cc;
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 ppen = Vector2(-font->padX, -font->padY /*- (font->lineHeight - font->baseY)*/);
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;
auto& ci = *s.cc;
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
- abstract osk input actions into a separate object/class heirarchy
- 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
... reimplement as a per-character lambda-"loop" {
status object with stuff
precalculate line stats, then loop through each
}
polish!
InputManager::OpenKeyboard
}