From d405490493665e73d041401233f88c4161b0b298 Mon Sep 17 00:00:00 2001 From: Sergey Petrov Date: Fri, 15 Dec 2017 22:17:52 +0700 Subject: [PATCH] Fix text measurement --- oxygine/src/DebugActor.cpp | 2 +- oxygine/src/Font.cpp | 16 +++-- oxygine/src/Font.h | 9 +-- oxygine/src/TextField.cpp | 13 ++-- oxygine/src/TextField.h | 4 +- oxygine/src/dev_tools/TexturesInspector.cpp | 4 +- oxygine/src/dev_tools/TreeInspectorLine.cpp | 2 +- oxygine/src/res/ResFontBM.cpp | 2 +- oxygine/src/text_utils/Aligner.cpp | 79 ++++++++------------- oxygine/src/text_utils/Aligner.h | 22 +++--- oxygine/src/text_utils/Node.cpp | 7 +- 11 files changed, 77 insertions(+), 83 deletions(-) diff --git a/oxygine/src/DebugActor.cpp b/oxygine/src/DebugActor.cpp index 508536878..9536e2f01 100644 --- a/oxygine/src/DebugActor.cpp +++ b/oxygine/src/DebugActor.cpp @@ -391,7 +391,7 @@ namespace oxygine _text->setText(s.str()); - setHeight(_text->getTextRect().size.y + _text->getY() + 3); + setHeight(_text->getTextRect(1.0f).size.y + _text->getY() + 3); _bg->setSize(getSize()); diff --git a/oxygine/src/Font.cpp b/oxygine/src/Font.cpp index 3600d323d..05540b67a 100644 --- a/oxygine/src/Font.cpp +++ b/oxygine/src/Font.cpp @@ -3,7 +3,7 @@ namespace oxygine { - Font::Font() : _size(0), _baselineDistance(0), _scale(1.0f), _sdf(false), _ignoreOptions(true) + Font::Font() : _size(0), _lineHeight(0), _lineGap(0), _scale(1.0f), _sdf(false), _ignoreOptions(true) { } @@ -11,12 +11,13 @@ namespace oxygine { } - void Font::init(const char* name, int realSize, int baselineDistance, int lineHeight, bool sdf) + void Font::init(const char* name, int realSize, int lineHeight, int lineGap, bool sdf) { setName(name); _sdf = sdf; _size = realSize; - _baselineDistance = baselineDistance; + _lineHeight = lineHeight; + _lineGap = lineGap; } void Font::addGlyph(const glyph& gl) @@ -66,9 +67,14 @@ namespace oxygine return g; } - int Font::getBaselineDistance() const + int Font::getLineHeight() const { - return _baselineDistance; + return _lineHeight; + } + + int Font::getLineGap() const + { + return _lineGap; } int Font::getSize() const diff --git a/oxygine/src/Font.h b/oxygine/src/Font.h index 45ae4e2cb..3a82df425 100644 --- a/oxygine/src/Font.h +++ b/oxygine/src/Font.h @@ -49,16 +49,16 @@ namespace oxygine Font(); ~Font(); - void init(const char* name, int size, int baselineDistance, int lineHeight, bool sdf = false); + void init(const char* name, int size, int lineHeight, int lineGap, bool sdf = false); void addGlyph(const glyph& g); void sortGlyphs() {} void setScale(float scale) { _scale = scale; } - void setBaselineDistance(int d) { _baselineDistance = d; } const glyph* getGlyph(int code, const glyphOptions& opt) const; - int getBaselineDistance() const; + int getLineHeight() const; + int getLineGap() const; int getSize() const; float getScale() const; bool isSDF() const; @@ -80,6 +80,7 @@ namespace oxygine bool _sdf; int _size; - int _baselineDistance; + int _lineHeight; + int _lineGap; }; } \ No newline at end of file diff --git a/oxygine/src/TextField.cpp b/oxygine/src/TextField.cpp index 64f7f199c..e9aa96150 100644 --- a/oxygine/src/TextField.cpp +++ b/oxygine/src/TextField.cpp @@ -13,6 +13,7 @@ #include "Serialize.h" #include "Material.h" +#include "Stage.h" namespace oxygine { @@ -56,7 +57,7 @@ namespace oxygine bool TextField::isOn(const Vector2& localPosition, float localScale) { - Rect r = getTextRect(localScale); + RectF r = getTextRect(localScale); r.expand(Point(_extendedIsOn, _extendedIsOn), Point(_extendedIsOn, _extendedIsOn)); return r.pointIn(Point((int)localPosition.x, (int)localPosition.y)); } @@ -288,7 +289,7 @@ namespace oxygine return const_cast(this)->getRootNode(_rtscale)->getSymbol(pos); } - const Rect& TextField::getTextRect(float localScale) const + const RectF& TextField::getTextRect(float localScale) const { const_cast(this)->getRootNode(localScale); return _textRect; @@ -296,7 +297,7 @@ namespace oxygine bool TextField::getBounds(RectF& r) const { - r = getTextRect().cast(); + r = getTextRect(Stage::instance->getScaleX()); return true; } @@ -306,7 +307,6 @@ namespace oxygine if (!_style.font) return _root; - float scale = 1.0f; const Font* font = _style.font->getClosestFont(globalScale, _style.fontSize, scale); @@ -334,7 +334,7 @@ namespace oxygine rd.end(); _root->finalPass(rd); - rd.bounds = (rd.bounds.cast() / rd.getScale()).cast(); + rd.bounds = rd.bounds / rd.getScale(); _textRect = rd.bounds; } @@ -426,7 +426,8 @@ namespace oxygine stream << " htmlMode"; } - Rect r = const_cast(this)->getTextRect(); + RectF r; + const_cast(this)->getBounds(r); stream << " textRect=(" << r.pos.x << ", " << r.pos.y << ", " << r.size.x << ", " << r.size.y << ")"; stream << "\n" << Actor::dump(options); diff --git a/oxygine/src/TextField.h b/oxygine/src/TextField.h index 5ee9386e0..2a4ca0576 100644 --- a/oxygine/src/TextField.h +++ b/oxygine/src/TextField.h @@ -24,7 +24,7 @@ namespace oxygine /**Returns current text style*/ const TextStyle& getStyle() const {return _style;} /**Returns text bounds*/ - const Rect& getTextRect(float localScale = 1.0f) const; + const RectF& getTextRect(float localScale) const; /**Returns current text*/ const std::string& getText() const { return _text; } const ResFont* getFont() const; @@ -115,7 +115,7 @@ namespace oxygine TextStyle _style; text::Node* _root; - Rect _textRect; + RectF _textRect; float _rtscale; int _realFontSize; diff --git a/oxygine/src/dev_tools/TexturesInspector.cpp b/oxygine/src/dev_tools/TexturesInspector.cpp index ba954fe41..ce25ff79b 100644 --- a/oxygine/src/dev_tools/TexturesInspector.cpp +++ b/oxygine/src/dev_tools/TexturesInspector.cpp @@ -65,7 +65,7 @@ namespace oxygine text->setBreakLongWords(true); - rect->setSize(text->getTextRect().size.cast() + Vector2(2, 2)); + rect->setSize(text->getTextRect(1.0f).size.cast() + Vector2(2, 2)); rect->setY((itemSize.y - rect->getHeight()) / 2.0f); } @@ -97,7 +97,7 @@ namespace oxygine ); - offsetY += text->getTextRect().getBottom() + 5; + offsetY += text->getTextRect(1.0f).getBottom() + 5; spActor content = new Actor; content->setX(2); diff --git a/oxygine/src/dev_tools/TreeInspectorLine.cpp b/oxygine/src/dev_tools/TreeInspectorLine.cpp index 5dc67b455..4918a44ce 100644 --- a/oxygine/src/dev_tools/TreeInspectorLine.cpp +++ b/oxygine/src/dev_tools/TreeInspectorLine.cpp @@ -53,7 +53,7 @@ namespace oxygine std::string desc = item->dump(0); tb->setHtmlText(desc); - Vector2 ts = tb->getTextRect().size.cast(); + Vector2 ts = tb->getTextRect(1.0f).size.cast(); if (ts.x < minWidth) ts.x = minWidth; diff --git a/oxygine/src/res/ResFontBM.cpp b/oxygine/src/res/ResFontBM.cpp index 38f054808..06b3d54a5 100644 --- a/oxygine/src/res/ResFontBM.cpp +++ b/oxygine/src/res/ResFontBM.cpp @@ -410,7 +410,7 @@ namespace oxygine gl.sw = width / downsample; gl.sh = height / downsample; gl.offset_x = xoffset / downsample; - gl.offset_y = yoffset / downsample - base; + gl.offset_y = yoffset / downsample - lineHeight; gl.advance_x = xadvance / downsample; gl.advance_y = 0; diff --git a/oxygine/src/text_utils/Aligner.cpp b/oxygine/src/text_utils/Aligner.cpp index afa7f91fb..6297f5477 100644 --- a/oxygine/src/text_utils/Aligner.cpp +++ b/oxygine/src/text_utils/Aligner.cpp @@ -6,13 +6,11 @@ namespace oxygine { namespace text { -#define GSCALE 1 - Aligner::Aligner(const TextStyle& Style, const Font* font, float gscale, const Vector2& size): width((int)size.x), height((int)size.y), _x(0), _y(0), _lineWidth(0), bounds(0, 0, 0, 0), style(Style), _scale(gscale), _font(font) + Aligner::Aligner(const TextStyle& Style, const Font* font, float scale, const Vector2& size): width((int)size.x), height((int)size.y), _x(0), _y(0), _lineWidth(0), bounds(0, 0, 0, 0), style(Style), _scale(scale), _font(font) { - //log::messageln("gscale %f, adjScale %f globscale %f, %d %f", gscale, _globalScale, _fontSize, fs); _line.reserve(50); - _lineSkip = (int)(_font->getBaselineDistance() * style.baselineScale) + style.linesOffset; + _lineSkip = _font->getLineHeight() * style.baselineScale + style.linesOffset; options = Style.options; } @@ -21,9 +19,9 @@ namespace oxygine } - int Aligner::_alignX(int rx) + float Aligner::_alignX(float rx) { - int tx = 0; + float tx = 0; switch (getStyle().hAlign) { case TextStyle::HALIGN_LEFT: @@ -40,9 +38,9 @@ namespace oxygine return tx; } - int Aligner::_alignY(int ry) + float Aligner::_alignY(float ry) { - int ty = 0; + float ty = 0; switch (getStyle().vAlign) { @@ -66,40 +64,29 @@ namespace oxygine void Aligner::begin() { _x = 0; - _y = 0; - - width = int(width * _scale); - height = int(height * _scale); + _y = getLineSkip(); + _lineWidth = 0; - bounds = Rect(_alignX(0), _alignY(0), 0, 0); - nextLine(); + width = width * _scale; + height = height * _scale; + bounds = RectF(_alignX(0), _alignY(0), 0, 0); } void Aligner::end() { - int ry = _y; - - if (getStyle().multiline) - { - nextLine(); - _y -= getLineSkip(); - } - else - { - _alignLine(_line); - } + _alignLine(_line); - bounds.setY(_alignY(ry)); - bounds.setHeight(ry); + bounds.setY(_alignY(_y)); + bounds.setHeight(_y); } - int Aligner::getLineWidth() const + float Aligner::getLineWidth() const { return _lineWidth; } - int Aligner::getLineSkip() const + float Aligner::getLineSkip() const { return _lineSkip; } @@ -109,14 +96,14 @@ namespace oxygine if (!ln.empty()) { //calculate real text width - int rx = 0; + float rx = 0; for (size_t i = 0; i < ln.size(); ++i) { Symbol& s = *ln[i]; - rx = std::max(s.x + s.gl.advance_x, rx); + rx = std::fmaxf(s.x + s.gl.advance_x, rx); } - int tx = _alignX(rx); + float tx = _alignX(rx); for (size_t i = 0; i < ln.size(); ++i) { @@ -126,16 +113,15 @@ namespace oxygine _lineWidth = rx; - bounds.setX(std::min(tx, bounds.getX())); - bounds.setWidth(std::max(_lineWidth, bounds.getWidth())); + bounds.setX(std::fminf(tx, bounds.getX())); + bounds.setWidth(std::fmaxf(_lineWidth, bounds.getWidth())); } } void Aligner::_nextLine(line& ln) { - _y += getLineSkip(); _alignLine(ln); - + _y += getLineSkip(); _lineWidth = 0; @@ -144,7 +130,7 @@ namespace oxygine void Aligner::nextLine() { - //assert(multiline == true); commented, becase even if multiline is false - there are breakLine markers, they could be used anyway + assert(getStyle().multiline); _nextLine(_line); _line.clear(); @@ -170,15 +156,14 @@ namespace oxygine s.y = _y + s.gl.offset_y; _x += s.gl.advance_x + getStyle().kerning; - int rx = s.x + s.gl.advance_x; + float rx = s.x + s.gl.advance_x; - _lineWidth = std::max(rx, _lineWidth); + _lineWidth = std::fmaxf(rx, _lineWidth); - // - if (_lineWidth > width && getStyle().multiline && (width > 0) && _line.size() > 1) + if (_lineWidth > width && getStyle().multiline && width > 0 && _line.size() > 1) { - int lastWordPos = (int)_line.size() - 1; + size_t lastWordPos = _line.size() - 1; for (; lastWordPos > 0; --lastWordPos) { if (_line[lastWordPos]->code == ' ' && _line[lastWordPos - 1]->code != ' ') @@ -188,20 +173,18 @@ namespace oxygine if (!lastWordPos) { if (style.breakLongWords) - lastWordPos = (int)_line.size() - 1; + lastWordPos = _line.size() - 1; else return 0; } - - int delta = (int)_line.size() - lastWordPos; + size_t delta = _line.size() - lastWordPos; line leftPart; leftPart.resize(delta + 1); leftPart.assign(_line.begin() + lastWordPos, _line.end()); _line.resize(lastWordPos); - nextLine(); - //line = leftPart; + nextLine(); for (size_t i = 0; i < leftPart.size(); ++i) { @@ -216,4 +199,4 @@ namespace oxygine return 0; } } -} \ No newline at end of file +} diff --git a/oxygine/src/text_utils/Aligner.h b/oxygine/src/text_utils/Aligner.h index 95e1d66e2..aa4b08b9a 100644 --- a/oxygine/src/text_utils/Aligner.h +++ b/oxygine/src/text_utils/Aligner.h @@ -18,7 +18,7 @@ namespace oxygine { Symbol(): x(0), y(0), code(0) {} - short x, y; + float x, y; int code; glyph gl; RectF destRect; @@ -42,31 +42,31 @@ namespace oxygine TextStyle style; - Rect bounds; - int width; - int height; + RectF bounds; + float width; + float height; int options; const Font* _font; private: - int getLineWidth()const; - int getLineSkip()const; + float getLineWidth()const; + float getLineSkip()const; typedef std::vector line; void _alignLine(line& ln); - int _alignX(int rx); - int _alignY(int ry); + float _alignX(float rx); + float _alignY(float ry); void _nextLine(line& ln); float _scale; - int _x, _y; + float _x, _y; line _line; - int _lineWidth; - int _lineSkip; + float _lineWidth; + float _lineSkip; }; } } \ No newline at end of file diff --git a/oxygine/src/text_utils/Node.cpp b/oxygine/src/text_utils/Node.cpp index 816db76ea..e8d01b033 100644 --- a/oxygine/src/text_utils/Node.cpp +++ b/oxygine/src/text_utils/Node.cpp @@ -180,7 +180,10 @@ namespace oxygine { Symbol& s = _data[i]; if (s.code == '\n') - rd.nextLine(); + { + if (rd.getStyle().multiline) + rd.nextLine(); + } else { const glyph* gl = font->getGlyph(s.code, opt); @@ -206,7 +209,7 @@ namespace oxygine } } - float mlt(int x, float sf) + float mlt(float x, float sf) { //return (x + 0.01f) / sf; return x / sf;