Fixed: Font size calculations for scaled text.

--HG--
branch : experimental-ui-scaling
This commit is contained in:
Nimetu 2018-06-22 19:44:12 +03:00
parent 375cedb09e
commit 1c142ef968
4 changed files with 166 additions and 141 deletions

View file

@ -129,6 +129,8 @@ namespace NLGUI
uint getFontHeight() const;
// get current font leg height, in pixels
uint getFontLegHeight() const;
// get current line height, in pixels
float getLineHeight() const;
// Set the display mode (supported with multiline only for now)
void setTextMode(TTextMode mode);
TTextMode getTextMode() const { return _TextMode; }
@ -149,11 +151,11 @@ namespace NLGUI
* When looking at standard edit box, we see that if a line is split accross to line with no
* This also returns the height of the line
*/
void getCharacterPositionFromIndex(sint index, bool lineEnd, sint &x, sint &y, sint &height) const;
void getCharacterPositionFromIndex(sint index, bool lineEnd, float &x, float &y, float &height) const;
/** From a coordinate relative to the BR BR corner of the text, return the index of a character.
* If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text)
*/
void getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &lineEnd) const;
void getCharacterIndexFromPosition(float x, float y, uint &index, bool &lineEnd) const;
/** From a character index, get the index of the line it belongs to, or -1 if the index is invalid
* \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index
*/
@ -330,7 +332,7 @@ namespace NLGUI
CFormatInfo Format;
public:
// build from a string, using the current text context
void build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces= 0);
void build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces= 0);
};
typedef std::vector<CWord> TWordVect;
@ -343,7 +345,7 @@ namespace NLGUI
// Clear the line & remove text contexts
void clear(NL3D::UTextContext &textContext);
// Add a new word (and its context) in the line + a number of spaces to append at the end of the line
void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale);
void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext);
void addWord(const CWord &word, float fontWidth);
uint getNumWords() const { return (uint)_Words.size(); }
CWord &getWord(uint index) { return _Words[index]; }
@ -404,7 +406,7 @@ namespace NLGUI
uint _TextSelectionEnd;
// First line X coordinate
sint _FirstLineX;
float _FirstLineX;
/// Dynamic tooltips
std::vector<CCtrlToolTip*> _Tooltips;

View file

@ -702,9 +702,9 @@ namespace NLGUI
sint32 maxPos= max(_CursorPos, _SelectCursorPos) + (sint32)_Prompt.length();
// get its position on screen
sint cxMinPos, cyMinPos;
sint cxMaxPos, cyMaxPos;
sint height;
float cxMinPos, cyMinPos;
float cxMaxPos, cyMaxPos;
float height;
_ViewText->getCharacterPositionFromIndex(minPos, false, cxMinPos, cyMinPos, height);
_ViewText->getCharacterPositionFromIndex(maxPos, false, cxMaxPos, cyMaxPos, height);
@ -755,8 +755,8 @@ namespace NLGUI
if (_BlinkState) // is the cursor shown ?
{
// get its position on screen
sint cx, cy;
sint height;
float cx, cy;
float height;
_ViewText->getCharacterPositionFromIndex(_CursorPos + (sint)_Prompt.length(), _CursorAtPreviousLineEnd, cx, cy, height);
// display the cursor
// get the texture for the cursor
@ -1482,7 +1482,7 @@ namespace NLGUI
if (_ViewText->getWReal() > _WReal)
{
// Check if cursor visible
sint xCursVT, xCurs, yTmp, hTmp;
float xCursVT, xCurs, yTmp, hTmp;
// Get the cursor pos from the BL of the viewtext
_ViewText->getCharacterPositionFromIndex(_CursorPos+(sint)_Prompt.size(), false, xCursVT, yTmp, hTmp);
// Get the cursor pos from the BL of the edit box

View file

@ -957,8 +957,31 @@ namespace NLGUI
CViewRenderer &rVR = *CViewRenderer::getInstance();
#if 0
//rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(64,64,64,255));
// debug text with mouse hover
if(CWidgetManager::getInstance()->getPointer())
{
// but must check first if mouse is over
sint32 x = CWidgetManager::getInstance()->getPointer()->getX();
sint32 y = CWidgetManager::getInstance()->getPointer()->getY();
bool mouseIn;
// use parent clip or self clip?
if(_OverExtendViewTextUseParentRect)
mouseIn= _Parent && _Parent->isIn(x,y);
else
mouseIn= isIn(x,y);
// if the mouse cursor is in the clip area
if(mouseIn) {
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255));
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255));
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255));
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(200,200,200,255));
}
}
#endif
// *** Out Of Clip?
sint32 ClipX, ClipY, ClipW, ClipH;
rVR.getClipWindow (ClipX, ClipY, ClipW, ClipH);
@ -1003,19 +1026,12 @@ namespace NLGUI
TextContext->setEmbolden (_Embolden);
TextContext->setOblique (_Oblique);
float y = _YReal;
//y += _LinesInfos[_LinesInfos.size()-1].StringLine / h;
// Y is the base line of the string, so it must be grown up.
y += _FontLegHeight;
sint y_line = _YReal+_FontLegHeight-2.0f*_Scale;
float y = _YReal * _Scale + _FontLegHeight;
if (_MultiMinLine > _Lines.size())
{
uint dy = getMultiMinOffsetY();
y += dy;
y_line += dy;
y += getMultiMinOffsetY() * _Scale;
}
// special selection code
@ -1056,7 +1072,7 @@ namespace NLGUI
{
CLine &currLine = *_Lines[i];
// current x position
float px = (float) (_XReal + ((i==0) ? (sint)_FirstLineX : 0));
float px = (float) (_XReal * _Scale + ((i==0) ? (sint)_FirstLineX : 0));
// draw each words of the line
for(uint k = 0; k < currLine.getNumWords(); ++k)
{
@ -1083,24 +1099,25 @@ namespace NLGUI
px += firstSpace;
// skip tabulation before current word
if(currWord.Format.TabX)
px= max(px, (float)(_XReal + currWord.Format.TabX*_FontWidth));
px= max(px, (float)(_XReal * _Scale + currWord.Format.TabX*_FontWidth));
// draw. We take floorf px to avoid filtering of letters that are not located on a pixel boundary
rVR.drawText (_RenderLayer, px, y, currWord.Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext);
float fx = px / _Scale;
float fy = y / _Scale;
rVR.drawText (_RenderLayer, fx, fy, currWord.Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext);
// Draw a line
if (_Underlined)
rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line, line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col);
rVR.drawRotFlipBitmap (_RenderLayer, fx, fy - _FontLegHeight*0.3f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col);
if (_StrikeThrough)
rVR.drawRotFlipBitmap (_RenderLayer, (sint)floorf(px), y_line + (_FontHeight / 2), line_width, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col);
rVR.drawRotFlipBitmap (_RenderLayer, fx, fy + _FontHeight*0.2f / _Scale, line_width / _Scale, 1.0f / _Scale, 0, false, rVR.getBlankTextureId(), col);
// skip word
px += currWord.Info.StringWidth;
}
// go one line up
y += (_FontHeight + _MultiLineSpace);
y_line += _FontHeight+_MultiLineSpace;
y += (_FontHeight + _MultiLineSpace * _Scale);
}
// reset selection
@ -1134,10 +1151,8 @@ namespace NLGUI
TextContext->setLetterColors(_LetterColors, _Index);
}
float y = _YReal;
// Y is the base line of the string, so it must be grown up.
y += _FontLegHeight;
float y = _YReal * _Scale + _FontLegHeight;
// special selection code
if(_TextSelection)
@ -1148,14 +1163,14 @@ namespace NLGUI
TextContext->setStringColor(_Index, col);
// draw
rVR.drawText (_RenderLayer, _XReal, y, _Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext);
rVR.drawText (_RenderLayer, _XReal, y / _Scale, _Index, ClipX, ClipY, ClipX+ClipW, ClipY+ClipH, *TextContext);
// Draw a line
if (_Underlined)
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_FontLegHeight-2.0f*_Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal - _FontLegHeight*0.3f/_Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col);
if (_StrikeThrough)
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+(_FontLegHeight/2), _WReal, 1, 0, false, rVR.getBlankTextureId(), col);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal + _FontHeight*0.2f / _Scale, _WReal, 1, 0, false, rVR.getBlankTextureId(), col);
// reset selection
if(_TextSelection)
@ -1204,7 +1219,6 @@ namespace NLGUI
}
}
}
}
// ***************************************************************************
@ -1344,6 +1358,7 @@ namespace NLGUI
// ***************************************************************************
void CViewText::setLineMaxW (sint nMaxW, bool invalidate)
{
nMaxW *= _Scale;
if(_LineMaxW!=nMaxW)
{
_LineMaxW = nMaxW;
@ -1395,19 +1410,25 @@ namespace NLGUI
// ***************************************************************************
uint CViewText::getFontWidth() const
{
return _FontWidth;
return _FontWidth / _Scale;
}
// ***************************************************************************
uint CViewText::getFontHeight() const
{
return _FontHeight;
return _FontHeight / _Scale;
}
// ***************************************************************************
uint CViewText::getFontLegHeight() const
{
return _FontLegHeight;
return _FontLegHeight / _Scale;
}
// ***************************************************************************
float CViewText::getLineHeight() const
{
return _FontHeight / _Scale + _MultiLineSpace;
}
// ***************************************************************************
@ -1418,7 +1439,7 @@ namespace NLGUI
{
// first line is always present even if _Lines is empty
uint nbLines = _MultiMinLine - std::max((sint)1, (sint)_Lines.size());
dy = nbLines * _FontHeight + (nbLines - 1) * _MultiLineSpace;
dy = (nbLines * _FontHeight + (nbLines - 1) * _MultiLineSpace * _Scale) / _Scale;
}
return dy;
}
@ -1434,7 +1455,7 @@ namespace NLGUI
linePushed= true;
}
// Append to the last line
_Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext, _Scale);
_Lines.back()->addWord(ucCurrentWord, 0, wordFormat, _FontWidth, *TextContext);
// reset the word
ucCurrentWord.clear();
}
@ -1450,11 +1471,12 @@ namespace NLGUI
ucstring ucCurrentWord;
CFormatInfo wordFormat;
// line state
float rWidthCurrentLine = 0, rWidthLetter;
float rWidthCurrentLine = 0;
bool linePushed= false;
// for all the text
uint textSize= (uint)_Text.size();
uint formatTagIndex= 0;
nMaxWidth *= _Scale;
for (i = 0; i < textSize; ++i)
{
if(isFormatTagChange(i, formatTagIndex))
@ -1487,21 +1509,20 @@ namespace NLGUI
ucstring ucStrLetter;
ucStrLetter= ucLetter;
si = TextContext->getStringInfo (ucStrLetter);
rWidthLetter = (si.StringWidth / _Scale);
if ((rWidthCurrentLine + rWidthLetter) > nMaxWidth)
if ((rWidthCurrentLine + si.StringWidth) > nMaxWidth)
{
flushWordInLine(ucCurrentWord, linePushed, wordFormat);
// reset line state, and begin with the cut letter
linePushed= false;
rWidthCurrentLine = rWidthLetter;
rWidthCurrentLine = si.StringWidth;
ucCurrentWord = ucLetter;
}
else
{
// Grow the current word
ucCurrentWord += ucLetter;
rWidthCurrentLine += rWidthLetter;
rWidthCurrentLine += si.StringWidth;
}
}
}
@ -1531,7 +1552,7 @@ namespace NLGUI
if(currLine[i].Format!=lineWordFormat)
{
// add the current lineWord to the line.
_Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale);
_Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext);
// get new lineWordFormat
lineWordFormat= currLine[i].Format;
// and clear
@ -1546,7 +1567,7 @@ namespace NLGUI
}
if(!lineWord.empty())
_Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext, _Scale);
_Lines.back()->addWord(lineWord, 0, lineWordFormat, _FontWidth, *TextContext);
// clear
currLine.clear();
@ -1564,7 +1585,7 @@ namespace NLGUI
static const ucstring spaceStr(" ");
// precLineWidth valid only id precedent line is part of same paragraph.
float precLineWidth= 0;
float lineWidth = (float)_FirstLineX * _Scale; // width of the current line
float lineWidth = (float)_FirstLineX; // width of the current line
uint numWordsInLine = 0; // number of words in the current line
bool isParagraphStart = true; // A paragraph is a group of characters between 2 \n
bool lineFeed;
@ -1575,6 +1596,7 @@ namespace NLGUI
CFormatInfo wordFormat;
uint formatTagIndex= 0;
//
nMaxWidth *= _Scale;
while (currPos != _Text.length())
{
TCharPos spaceEnd;
@ -1655,7 +1677,7 @@ namespace NLGUI
// compute size of spaces/Tab + word
newLineWidth = lineWidth + numSpaces * _SpaceWidth;
newLineWidth = max(newLineWidth, (float)wordFormat.TabX*_FontWidth);
newLineWidth+= si.StringWidth / _Scale;
newLineWidth+= si.StringWidth;
}
//
// Does the word go beyond the end of line ?
@ -1707,7 +1729,7 @@ namespace NLGUI
{
uint maxNumSpaces = std::max(1U, (uint) (nMaxWidth / _SpaceWidth));
CWord spaceWord; // a word with only spaces in it
spaceWord.build (ucstring (""), *TextContext, _Scale, maxNumSpaces);
spaceWord.build (ucstring (""), *TextContext, maxNumSpaces);
spaceWord.Format= wordFormat;
_Lines.push_back(TLineSPtr(new CLine));
_Lines.back()->addWord(spaceWord, _FontWidth);
@ -1730,13 +1752,13 @@ namespace NLGUI
{
oneChar = wordValue[currChar];
si = TextContext->getStringInfo(oneChar);
if ((uint) (px + si.StringWidth / _Scale) > nMaxWidth) break;
px += si.StringWidth / _Scale;
if ((uint) (px + si.StringWidth) > nMaxWidth) break;
px += si.StringWidth;
}
currChar = std::max((uint) 1, currChar); // must fit at least one character otherwise there's an infinite loop
wordValue = _Text.substr(spaceEnd, currChar);
CWord word;
word.build(wordValue, *TextContext, _Scale, numSpaces);
word.build(wordValue, *TextContext, numSpaces);
word.Format= wordFormat;
_Lines.push_back(TLineSPtr(new CLine));
float roomForSpaces = (float) nMaxWidth - word.Info.StringWidth;
@ -1771,7 +1793,7 @@ namespace NLGUI
if (!wordValue.empty() || numSpaces != 0)
{
CWord word;
word.build(wordValue, *TextContext, _Scale, numSpaces);
word.build(wordValue, *TextContext, numSpaces);
word.Format= wordFormat;
// update line width
_Lines.back()->addWord(word, _FontWidth);
@ -1890,24 +1912,25 @@ namespace NLGUI
_Lines.pop_back();
CViewText::CLine *endLine = new CViewText::CLine;
CViewText::CWord w;
w.build(_OverflowText, *TextContext, _Scale);
w.build(_OverflowText, *TextContext);
endLine->addWord(w, _FontWidth);
_Lines.push_back(TLineSPtr(endLine));
}
}
// Calculate size
float rMultiLineSpace = _MultiLineSpace * _Scale;
float rTotalW = 0;
for (uint i = 0; i < _Lines.size(); ++i)
{
rTotalW = std::max(_Lines[i]->getWidth() + ((i==0)?_FirstLineX:0), rTotalW);
}
_W = (sint)ceilf(rTotalW);
_H = std::max(_FontHeight, ceilf(_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * _MultiLineSpace));
_W = (sint)ceilf(rTotalW / _Scale);
_H = std::max(_FontHeight / _Scale, ceilf((_FontHeight * _Lines.size() + std::max(0, sint(_Lines.size()) - 1) * rMultiLineSpace) / _Scale));
// See if we should pretend to have at least X lines
if (_MultiMinLine > 1)
_H = std::max(_H, sint(_FontHeight * _MultiMinLine + (_MultiMinLine - 1) * _MultiLineSpace));
_H = std::max(_H, sint((_FontHeight * _MultiMinLine + (_MultiMinLine - 1) * rMultiLineSpace)/_Scale));
// Compute tooltips size
if (!_Tooltips.empty())
@ -1916,7 +1939,6 @@ namespace NLGUI
for (uint j=0 ; j<_Lines[i]->getNumWords() ; ++j)
{
CWord word = _Lines[i]->getWord(j);
// float w = _Lines[i]->getWidth();
if (word.Format.IndexTt != -1)
{
@ -1924,7 +1946,7 @@ namespace NLGUI
{
CCtrlToolTip *pTooltip = _Tooltips[word.Format.IndexTt];
sint y = (sint) ceilf((_FontHeight + _MultiLineSpace) * (_Lines.size() - i - 1));
sint y = (sint) ceilf(((_FontHeight + rMultiLineSpace) * (_Lines.size() - i - 1))/_Scale);
pTooltip->setX(0);
pTooltip->setY(y);
@ -1943,11 +1965,10 @@ namespace NLGUI
// Common case: no W clamp
_Index = TextContext->textPush (_Text);
_Info = TextContext->getStringInfo (_Index);
_Info.StringWidth /= _Scale;
_W = (sint)ceilf(_Info.StringWidth);
_W = (sint)ceilf(_Info.StringWidth / _Scale);
// Rare case: clamp W => recompute slowly, cut letters
if(_W>_LineMaxW)
if(_Info.StringWidth > _LineMaxW)
{
TextContext->erase (_Index);
@ -1957,18 +1978,14 @@ namespace NLGUI
ucCurrentLine.reserve(_Text.size());
// Append ... to the end of line
float dotWidth;
float dotWidth = 0.f;
if (_OverflowText.size() > 0)
{
si = TextContext->getStringInfo (ucstring(_OverflowText));
dotWidth = si.StringWidth / _Scale;
}
else
{
dotWidth = 0.0f;
dotWidth = si.StringWidth;
}
float rWidthCurrentLine = 0, rWidthLetter;
float rWidthCurrentLine = 0;
// for all the text
if (_ClampRight)
{
@ -1978,8 +1995,7 @@ namespace NLGUI
ucstring ucStrLetter;
ucStrLetter= ucLetter;
si = TextContext->getStringInfo (ucStrLetter);
rWidthLetter = (si.StringWidth / _Scale);
if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW)
if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW)
{
break;
}
@ -1987,7 +2003,7 @@ namespace NLGUI
{
// Grow the current line
ucCurrentLine += ucLetter;
rWidthCurrentLine += rWidthLetter;
rWidthCurrentLine += si.StringWidth;
}
}
@ -2005,8 +2021,7 @@ namespace NLGUI
ucstring ucStrLetter;
ucStrLetter= ucLetter;
si = TextContext->getStringInfo (ucStrLetter);
rWidthLetter = (si.StringWidth / _Scale);
if ((rWidthCurrentLine + rWidthLetter + dotWidth) > _LineMaxW)
if ((rWidthCurrentLine + si.StringWidth + dotWidth) > _LineMaxW)
{
break;
}
@ -2014,7 +2029,7 @@ namespace NLGUI
{
// Grow the current line
ucCurrentLine = ucLetter + ucCurrentLine;
rWidthCurrentLine += rWidthLetter;
rWidthCurrentLine += si.StringWidth;
}
}
@ -2028,14 +2043,13 @@ namespace NLGUI
// And so setup this trunc text
_Index = TextContext->textPush (ucCurrentLine);
_Info = TextContext->getStringInfo (_Index);
_Info.StringWidth /= _Scale;
_W = (sint)ceilf(_Info.StringWidth);
_W = (sint)ceilf(_Info.StringWidth / _Scale);
_SingleLineTextClamped= true;
}
// same height always
_H = (sint)ceilf(_FontHeight);
_H = (sint)ceilf(_FontHeight / _Scale);
}
_InvalidTextContext= false;
@ -2072,12 +2086,12 @@ namespace NLGUI
if (_ClampRight)
{
sint32 parentRight = parent->getXReal() + parent->getWReal() - (sint32) _AutoClampOffset;
setLineMaxW(ceilf(std::max((sint32) 0, parentRight - _XReal) / _Scale));
setLineMaxW(std::max((sint32) 0, parentRight - _XReal));
}
else
{
sint32 parentLeft = parent->getXReal() + (sint32) _AutoClampOffset;
setLineMaxW(ceilf(std::max((sint32) 0, _XReal + _WReal - parentLeft) / _Scale));
setLineMaxW(std::max((sint32) 0, _XReal + _WReal - parentLeft));
}
}
}
@ -2194,7 +2208,7 @@ namespace NLGUI
}
// ***************************************************************************
void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, sint &x, sint &y, sint &height) const
void CViewText::getCharacterPositionFromIndex(sint index, bool cursorAtPreviousLineEnd, float &x, float &y, float &height) const
{
NLMISC::clamp(index, 0, (sint) _Text.length());
NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName);
@ -2204,18 +2218,19 @@ namespace NLGUI
TextContext->setFontSize (_FontSize*_Scale);
TextContext->setEmbolden (_Embolden);
TextContext->setOblique (_Oblique);
// CViewRenderer &rVR = *CViewRenderer::getInstance();
height = getFontHeight();
height = getLineHeight();
//
if (_MultiLine)
{
uint dy = getMultiMinOffsetY();
float fx, fy;
float dy = getMultiMinOffsetY() * _Scale;
float nMaxWidth = getCurrentMultiLineMaxW() * _Scale;
uint charIndex = 0;
// special case for end of text
if (index == (sint) _Text.length())
{
y = dy;
fy = dy;
if (_Lines.empty())
{
x = 0;
@ -2223,10 +2238,12 @@ namespace NLGUI
else
{
CLine &lastLine = *_Lines.back();
x = (sint) (lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth());
sint nMaxWidth = getCurrentMultiLineMaxW();
x = std::min(x, nMaxWidth);
fx = lastLine.getWidth() + lastLine.getEndSpaces() * lastLine.getSpaceWidth();
fx = std::min(fx, nMaxWidth);
}
x = fx / _Scale;
y = fy / _Scale;
return;
}
for(sint i = 0; i < (sint) _Lines.size(); ++i)
@ -2235,10 +2252,12 @@ namespace NLGUI
{
// should display the character at the end of previous line
CLine &currLine = *_Lines[i - 1];
y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - i) + dy);
x = (sint) (currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth());
sint nMaxWidth = getCurrentMultiLineMaxW();
x = std::min(x, nMaxWidth);
fy = (_FontHeight + _MultiLineSpace * _Scale) * (_Lines.size() - i) + dy;
fx = currLine.getWidth() + currLine.getEndSpaces() * currLine.getSpaceWidth();
fx = std::min(fx, nMaxWidth);
x = fx / _Scale;
y = fy / _Scale;
return;
}
CLine &currLine = *_Lines[i];
@ -2246,14 +2265,16 @@ namespace NLGUI
if ((sint) newCharIndex > index)
{
// ok, this line contains the character, now, see which word contains it.
y = (sint) ((_FontHeight + _MultiLineSpace) * (_Lines.size() - 1 - i) + dy);
fy = (_FontHeight + _MultiLineSpace * _Scale) * (_Lines.size() - 1 - i) + dy;
// see if the index is in the spaces at the end of line
if (index - charIndex >= currLine.getNumChars())
{
uint numSpaces = index - charIndex - currLine.getNumChars();
x = (sint) (currLine.getWidth() + numSpaces * _SpaceWidth);
sint nMaxWidth = getCurrentMultiLineMaxW();
x = std::min(x, nMaxWidth);
fx = currLine.getWidth() + numSpaces * _SpaceWidth;
fx = std::min(fx, nMaxWidth);
x = fx / _Scale;
y = fy / _Scale;
return;
}
// now, search containing word in current line
@ -2271,15 +2292,19 @@ namespace NLGUI
ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces);
// compute the size
UTextContext::CStringInfo si = TextContext->getStringInfo(subStr);
x = (sint) ceilf(px + si.StringWidth / _Scale + currWord.NumSpaces * currLine.getSpaceWidth());
height = getFontHeight();
fx = px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth();
x = fx / _Scale;
y = fy / _Scale;
return;
}
else
{
// character is in the spaces preceding the word
x = (sint) ceilf(px + currLine.getSpaceWidth() * (index - charIndex));
height = getFontHeight();
fx = px + currLine.getSpaceWidth() * (index - charIndex);
x = fx / _Scale;
y = fy / _Scale;
return;
}
}
@ -2303,11 +2328,11 @@ namespace NLGUI
}
// ***************************************************************************
// Tool fct : From a word and a x coordinate, give the matching character index
static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext, float scale)
// Tool fct : From a word and a x coordinate (font scale), give the matching character index
static uint getCharacterIndex(const ucstring &textValue, float x, NL3D::UTextContext &textContext)
{
float px = 0.f;
float sw;
UTextContext::CStringInfo si;
ucstring singleChar(" ");
uint i;
@ -2316,13 +2341,12 @@ namespace NLGUI
// get character width
singleChar[0] = textValue[i];
si = textContext.getStringInfo(singleChar);
sw = si.StringWidth / scale;
px += sw;
px += si.StringWidth;
// the character is at the i - 1 position
if (px > x)
{
// if the half of the character is after the cursor, then prefer select the next one (like in Word)
if(px-sw/2 < x)
if(px-si.StringWidth/2.f < x)
i++;
break;
}
@ -2331,10 +2355,13 @@ namespace NLGUI
}
// ***************************************************************************
void CViewText::getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &cursorAtPreviousLineEnd) const
void CViewText::getCharacterIndexFromPosition(float x, float y, uint &index, bool &cursorAtPreviousLineEnd) const
{
NL3D::UTextContext *TextContext = CViewRenderer::getTextContext(_FontName);
x *= _Scale;
y = roundf(y * _Scale);
// setup the text context
TextContext->setHotSpot (UTextContext::BottomLeft);
TextContext->setShaded (_Shadow);
@ -2347,7 +2374,7 @@ namespace NLGUI
uint charPos = 0;
if (_MultiLine)
{
y -= getMultiMinOffsetY();
y -= getMultiMinOffsetY() * _Scale;
// seek the line
float py = 0.f;
if (py > y)
@ -2359,7 +2386,7 @@ namespace NLGUI
sint line;
for (line = (uint)_Lines.size() - 1; line >= 0; --line)
{
float newPy = py + _FontHeight + _MultiLineSpace;
float newPy = py + _FontHeight + _MultiLineSpace * _Scale;
if (newPy > y)
{
break;
@ -2392,6 +2419,7 @@ namespace NLGUI
return;
}
cursorAtPreviousLineEnd = false;
float px = (float)_FirstLineX;
for(uint k = 0; k < currLine.getNumWords(); ++k)
{
@ -2408,14 +2436,12 @@ namespace NLGUI
: 0;
clamp(numSpaces, 0, (sint)currWord.NumSpaces);
index = numSpaces + charPos;
cursorAtPreviousLineEnd = false;
return;
}
else
{
// the coord is in the word itself
index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, (float) x - (px + spacesWidth), *TextContext, _Scale);
cursorAtPreviousLineEnd = false;
index = charPos + currWord.NumSpaces + getCharacterIndex(currWord.Text, x - (px + spacesWidth), *TextContext);
return;
}
}
@ -2423,7 +2449,6 @@ namespace NLGUI
charPos += (uint)currWord.Text.length() + currWord.NumSpaces;
}
index = charPos;
cursorAtPreviousLineEnd = false;
return;
}
else
@ -2439,7 +2464,7 @@ namespace NLGUI
index = 0;
return;
}
index = getCharacterIndex(_Text, (float) x, *TextContext, _Scale);
index = getCharacterIndex(_Text, x, *TextContext);
return;
}
}
@ -2507,21 +2532,21 @@ namespace NLGUI
// ***************************************************************************
uint CViewText::getFirstLineX() const
{
return _FirstLineX;
return _FirstLineX / _Scale;
}
// ***************************************************************************
uint CViewText::getLastLineW () const
{
if (!_Lines.empty())
return (uint)_Lines.back()->getWidth();
return (uint)_Lines.back()->getWidth() / _Scale;
return 0;
}
// ***************************************************************************
void CViewText::setFirstLineX(sint firstLineX)
{
_FirstLineX = firstLineX;
_FirstLineX = firstLineX * _Scale;
}
/////////////////////////////////////
@ -2540,10 +2565,10 @@ namespace NLGUI
}
// ***************************************************************************
void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext, float scale)
void CViewText::CLine::addWord(const ucstring &text, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext)
{
CWord word;
word.build(text, textContext, scale, numSpaces);
word.build(text, textContext, numSpaces);
word.Format= wordFormat;
addWord(word, fontWidth);
}
@ -2587,13 +2612,12 @@ namespace NLGUI
}
// ***************************************************************************
void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, float scale, uint numSpaces)
void CViewText::CWord::build(const ucstring &text, NL3D::UTextContext &textContext, uint numSpaces)
{
Text = text;
NumSpaces = numSpaces;
Index = textContext.textPush(text);
Info = textContext.getStringInfo(Index);
Info.StringWidth /= scale;
}
// ***************************************************************************
@ -2667,7 +2691,7 @@ namespace NLGUI
si = TextContext->getStringInfo(wordValue);
// compute size of spaces + word
lineWidth += numSpaces * _SpaceWidth + si.StringWidth / _Scale;
lineWidth += numSpaces * _SpaceWidth + si.StringWidth;
currPos = wordEnd;
}
@ -2679,7 +2703,7 @@ namespace NLGUI
linePos = lineEnd+1;
}
return (sint32)ceilf(maxWidth);
return (sint32)ceilf(maxWidth / _Scale);
}
// ***************************************************************************
@ -2696,7 +2720,7 @@ namespace NLGUI
if (_TextMode == ClipWord)
{
// No largest font parameter, return the font height
return (sint32)ceilf(_FontHeight);
return (sint32)ceilf(_FontHeight / _Scale);
}
// If we can't clip the words, return the size of the largest word
else if ((_TextMode == DontClipWord) || (_TextMode == Justified))
@ -2733,16 +2757,15 @@ namespace NLGUI
si = TextContext->getStringInfo(wordValue);
// Larger ?
float stringWidth = (si.StringWidth / _Scale);
if (stringWidth>maxWidth)
maxWidth = stringWidth;
if (maxWidth < si.StringWidth)
maxWidth = si.StringWidth;
// Next word
currPos = wordEnd;
}
}
return ceilf(maxWidth);
return ceilf(maxWidth / _Scale);
}
// ***************************************************************************
@ -2796,16 +2819,16 @@ namespace NLGUI
si = TextContext->getStringInfo(chars);
}
// add a padding of 1 pixel else the top will be truncated
_FontHeight = (si.StringHeight / _Scale) + 1;
_FontLegHeight = si.StringLine / _Scale;
_FontHeight = si.StringHeight + 1;
_FontLegHeight = si.StringLine;
// Space width
si = TextContext->getStringInfo(ucstring(" "));
_SpaceWidth = si.StringWidth / _Scale;
_SpaceWidth = si.StringWidth;
// Font Width
si = TextContext->getStringInfo(ucstring("_"));
_FontWidth = si.StringWidth / _Scale;
_FontWidth = si.StringWidth;
}

View file

@ -383,10 +383,10 @@ class CAHEditPreviousLine : public CAHEdit
// .. so do nothing
return;
}
sint cx, cy;
sint height;
float cx, cy;
float height;
_GroupEdit->getViewText()->getCharacterPositionFromIndex(cursorPosInText, _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
cy += height + _GroupEdit->getViewText()->getMultiLineSpace();
cy += _GroupEdit->getViewText()->getLineHeight();
uint newCharIndex;
bool newLineEnd;
_GroupEdit->getViewText()->getCharacterIndexFromPosition(cx, cy, newCharIndex, newLineEnd);
@ -401,8 +401,8 @@ class CAHEditPreviousLine : public CAHEdit
}
_GroupEdit->setCursorAtPreviousLineEnd(false);
// takes character whose X is closer to the current X
sint cx0, cx1;
sint cy0, cy1;
float cx0, cx1;
float cy0, cy1;
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)
@ -446,8 +446,8 @@ class CAHEditNextLine : public CAHEdit
}
else if (_GroupEdit->getViewText()->getMultiLine())
{
sint cx, cy;
sint height;
float cx, cy;
float height;
_GroupEdit->getViewText()->getCharacterPositionFromIndex(_GroupEdit->getCursorPos() + (sint)_GroupEdit->getPrompt().length(), _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
if (cy != 0)
{
@ -466,8 +466,8 @@ class CAHEditNextLine : public CAHEdit
}
_GroupEdit->setCursorAtPreviousLineEnd(false);
// takes character whose X is closer to the current X
sint cx0, cx1;
sint cy0, cy1;
float cx0, cx1;
float cy0, cy1;
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)