diff --git a/libstarlight/source/starlight/dialog/OSK.cpp b/libstarlight/source/starlight/dialog/OSK.cpp index eb022a8..3cf42ca 100644 --- a/libstarlight/source/starlight/dialog/OSK.cpp +++ b/libstarlight/source/starlight/dialog/OSK.cpp @@ -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(); } diff --git a/libstarlight/source/starlight/gfx/BitmapFont.cpp b/libstarlight/source/starlight/gfx/BitmapFont.cpp index dc455de..baf15cf 100644 --- a/libstarlight/source/starlight/gfx/BitmapFont.cpp +++ b/libstarlight/source/starlight/gfx/BitmapFont.cpp @@ -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; + + 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 oPen = pen; - float longest = 0; - float wordlen = 0; - float plen = 0; + Vector2 measure; + bool found = false; - 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; - } - - 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; + 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; } - } - 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; - } - - 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; + ForChar(msg, [&, this, pt, tl](auto& s){ + if (s.lineNum < tl) return false; // skip + if (s.lineNum > tl) { // huh. + return true; } - } - // 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.i == s.lineEnd) { + if (s.i == s.lineStart) { // if blank line... + idx = s.i; + return true; + } + return false; // skip newlines on non-blank lines + } + + 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 len; + return idx; } void BitmapFont::ForChar(const std::string& msg, std::function func, float maxWidth) { @@ -201,6 +163,7 @@ void BitmapFont::ForChar(const std::string& msg, std::function lines; @@ -209,7 +172,6 @@ void BitmapFont::ForChar(const std::string& msg, std::function= len) ? '\n' : msg[i]; state.cc = &(Char(state.c)); state.i = i; diff --git a/libstarlight/source/starlight/gfx/FontBMF.cpp b/libstarlight/source/starlight/gfx/FontBMF.cpp index 761f8ec..62e0899 100644 --- a/libstarlight/source/starlight/gfx/FontBMF.cpp +++ b/libstarlight/source/starlight/gfx/FontBMF.cpp @@ -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); diff --git a/libstarlight/todo.txt b/libstarlight/todo.txt index dfc9719..7843083 100644 --- a/libstarlight/todo.txt +++ b/libstarlight/todo.txt @@ -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 }