Get Content Size of string - c++

Is it possible to get content size of a string in c++. I'm not talking about length here. I want to place strings in a row one after the other, say on a label but don't want to get content size of label.I need to get space a string covers on screen.

What you ask is not possible with C++ string.
May be you could use something like this, with NSString and sizeWithFont:
NSString *str= #"Hello, World!"
UIFont * font = [UIFont fontWithName:#"YourFontName" size:11];
CGSize supposedSize = [str sizeWithFont:font constrainedToSize:CGSizeMake(100, 100)];
CCLabelTTF *label = [CCLabelTTF labelWithString:str dimensions:supposedSize fontName:#"YourFontName" fontSize:11];
to find out the height and width of the text in cocos2d.

Related

Setting CCLabelTTF's width by getting the NSSting's text width is not working fine?

I am a iphone game developer. Right now i am developing a book app for children. For that i need to change the color of the cclabel to change word by word with a voice dictating the text in the background. To make it work as a initial process
NSString *pstring1 = #"The moon is a big eye";
int ix = 600,iy = 300;
NSArray *str1 = [pstring1 componentsSeparatedByString:#" "];
NSLog(#"str1 %#",str1);
for(NSString* st in str1)
{
CCLOG(#"STRING IS %# POSITION IS %d",st,ix);
CGFloat wid= 0;
CGFloat ss = [st sizeWithFont: [UIFont systemFontOfSize:25]].width;
wid = ss+(ss/10);
CCLabelTTF * labels = [CCLabelTTF labelWithString:st fontName:#"Marker Felt" fontSize:25 ];
[labels setPosition:CGPointMake(ix, iy)];
[labels setColor:ccBLUE];
ix+=wid+5;
[self addChild:labels];
For example i separated a string with white space and added it to an NSArray. And in the for loop i am getting the text width of the string in the array one by one using sizeWithFont and i have added it as CGFloat value.And i am creating cclabel for each word in the array and incrementing the width size according the word's width in the array which is saved in the CGFloat. The problem is there is more white space between each cclabel or it merges with one another.I don't know whether i am correct or wrong The output looks like this http://screencast.com/t/p8Rj8GKZ . Please help me to sort out this issue. If this is issue is sorted out means i will use timer and change the color of the each cclabel to show the word to word color change effect.
Finally i fixed the issue which i have mentioned above
I have just set the contentsize of the label to zero and now all the unwanted white space between the one word to the another got disappeared
[labels setContentSize:CGSizeZero];

Getting dimensions of text in SFML

I was wondering how i get the dimensions of my text in SFML?
I tried to do it like this:
sf::Text text("Hello SFML", font, 50);
// using text.getRect()
// i also tried getScale() & getSize()
// neither are correct
text.setPosition( window.getSize().y/2 - text.getRect().y,50 );
Does any one know ?
Thanks :)
Looking at the documentation it seems like the function
getLocalBounds could be of use to you. The line would be:
float width = text.getLocalBounds().width;
I'm not sure if the sf::Text object would add any padding on the ends of the bounding rectangle.
Alternatively, you could make use of findCharacterPos with something like:
float width = text.findCharacterPos(numChars - 1).x - text.findCharacterPos(0).x;
where numChars is the number of characters in the string of your text object. However, since findCharacterPos will return global coordinates, it's probably more convenient to use getLocalBounds, this way you don't have to worry about whether your text object has any transformations applied to it.
You can use getGlobalBounds() to get the size/coordinates after a transformation (rotation, scale, move...).
Otherwise it's getLocalBounds().
Doc: http://www.sfml-dev.org/documentation/2.3.1/classsf_1_1Text.php

How to override tab width in qt?

I just need to know how to change the tab size in Qt in a QTextEdit. My Google and stackoverflow search returned me null. Thanks in advance.
If you want to create a source code editor using QTextEdit, you should first assign a fixed-width (monospace) font. This ensures that all characters have the same width:
QFont font;
font.setFamily("Courier");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
font.setPointSize(10);
QTextEdit* editor = new QTextEdit();
editor->setFont(font);
If you want to set a tab width to certain amount of spaces, as it is typically done in text editors, use QFontMetrics to compute the size of one space in pixels:
const int tabStop = 4; // 4 characters
QFontMetrics metrics(font);
editor->setTabStopWidth(tabStop * metrics.width(' '));
The QTextEdit::tabStopWidth property might solve your problem (see here for Documentation...)
While the question about how to set tab stop width has been answered already; computing the correct tab width in pixels is still (or again?) an open question.
Since Qt 5.10, QTextEdit::tabStopWidth is marked as obsolete and QTextEdit::tabStopDistance was introduced. tabStopWidth was integer, tabStopDistance is double.
Why so complicated?
Setting n * QFontMetrics::width(' ') as tab stop width makes troubles because font_metrics.width returns an integer. Even if you have a monospace standard font, the width of a single character is actually not an integer, so QFontMetrics::width returns an inaccurate measure.
If you compare the appearance of the strings ........| and \t\t\t\t| (\t = tab, n=2), you will see that the pipes are not aligned properly. It will become worse the more tabs you insert.
Solution
You could do what #Ferdinand Beyer proposed, but it will slightly change the typeface. I also had to adapt his method to make it work. However, there's a much simpler approach which exploits that you can set tabStopDistance now with double precision:
static constexpr int tab_width_char = 2;
m_text_edit->setFont(QFont("Courier", 12));
const auto font_metrics = m_text_edit->fontMetrics();
static constexpr int big_number = 1000; // arbitrary big number.
const QString test_string(" ");
// compute the size of a char in double-precision
const int single_char_width = font_metrics.width(test_string);
const int many_char_width = font_metrics.width(test_string.repeated(big_number));
const double single_char_width_double = many_char_width / double(big_number);
// set the tab stop with double precision
m_text_edit->setTabStopDistance(tab_width_char * single_char_width_double);
This would be so much simpler if Qt offered a way to get the width of a single character as double.
While #Ferdinand Beyer's solution will work on some systems, generally fonts are not guaranteed to have integer metrics. e.g 12pt DejaVu Sans Mono on my Linux setup has character width of 9.625. The best solution I've found is add some letter spacing to get pixel-perfect alignment.
int tabstop = 4;
QFontMetricsF fm (ui->textEdit->font());
auto stopWidth = tabstop * fm.width(' ');
auto letterSpacing = (ceil(stopWidth) - stopWidth) / tabstop;
auto font = ui->textEdit->font();
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
ui->textEdit->setFont(font);
ui->textEdit->setTabStopWidth(ceil(stopWidth));
Computing a product of a size of one space and num spaces is not always precise (tested under macOS, Monaco font), presumably due to some gaps in between the characters in the real string.
A better solution would be to measure the length of the string containing tabStop spaces:
const int tabStop = 4; // 4 characters
QString spaces;
for (int i = 0; i < tabStop; ++i) {
spaces += " ";
}
QFontMetrics metrics(font);
editor->setTabStopWidth(metrics.width(spaces));

How to get real size of a CCLabelTTF in cocos2d?

I have a CCLabelTTF with a dynamic text. Let's say it has a maxsize of 200,200. I create it:
CCLabelTTF * label = [CCLabelTTF labelWithString:#"Hello!" dimensions:CGSizeMake(200,200) alignment:UITextAlignmentLeft lineBreakMode:UILineBreakModeWordWrap fontName:#"Helvetica" fontSize:15];
This works nicely.
But I have to put something right under, therefore I need to know the height of the text. I've tried label.texture.contentSize, label.contentSize. They both is 200,200.
What can I do here?
I'm using cocos2d 1.x
You can use NSString's sizeWithFont methods.
NSString *hello = #"Hello!"
UIFont *font = ...
CGSize *textSize = [hello sizeWithFont:font constrainedToSize:CGSizeMake(200, 200) lineBreakMode:UILineBreakModeWordWrap];
This should tell you the exact size of the text.
UIFont * font = [UIFont fontWithName:#"HelveticaNeue" size:15];
CGSize realSize = [message sizeWithFont:font constrainedToSize:CGSizeMake(210, 200) lineBreakMode:UILineBreakModeWordWrap];
label = [CCLabelTTF labelWithString:message dimensions:realSize alignment:UITextAlignmentCenter lineBreakMode:UILineBreakModeWordWrap fontName:#"HelveticaNeue" fontSize:15];
This is what I ended up doing based on #Ben answer. It works perfectly!

Cannot get text with Unicode (including Chinese) characters to line up with MFC using a CRichEditCtrl

I have a CRichEditCtrl (actually I have a class that is a subclass of a CRichEditCtrl, a class that I defined) that is populated by many lines of text with both horizontal and vertical scroll bars. The purpose of this control is to display a string that is searched for in a larger text along with n characters to the right and left (e.g. if the user searches for "the" then they would get a list of all the instances of "the" in the text with (if n = 100) 100 characters to the left and right of each found instance to provide context).
The query string needs to be lined up between each row. Before this program had Unicode support, just setting the font to Courier did the trick, but now that I've enabled Unicode support, this no longer works.
I've tried using monospaced fonts, but as far as I can tell, there aren't any that are for all characters. It seems to me that the latin characters all have one size, and the Chinese characters have another (I've noticed lines of text with all latin characters line up and ones with all Chinese characters line up, but ones with both do not line up).
I've also tried center aligning the text. Since the query string in each line is in the exact center, they should all line up, but I cannot seem to get this to work, the SetParaFormat call seems to just get ignored. Here's the code I used for that:
long spos, epos;
GetSel(spos, epos);
PARAFORMAT Pfm;
GetParaFormat(Pfm);
Pfm.dwMask = (Pfm.dwMask | PFM_ALIGNMENT);
Pfm.wAlignment = PFA_CENTER;
SetSel(0, -1);
SetParaFormat(Pfm);
SetSel(spos, epos);
I do this everytime text is inserted in the ctrl, but it has no affect on the program.
Is there anyway to get the query word in each line of text to line up even when there are interspersed Chinese and latin characters? (and possibly any other character set)
See http://msdn.microsoft.com/en-us/library/bb787940(v=vs.85).aspx, in particular the cTabCount and rgxTabs members of the PARAFORMAT (or PARAFORMAT2) structure, which allow you to set tabstops.
Okay so I managed to solve it. For future reference, here's what I did:
First, I tried to find a monospaced font, but I was unable to find any that were truly monospaced (had latin and chinese characters as the same width).
Next, I tried to center the text in the window. I was unable to do this until I realized that having Auto HScroll set to true (ES_AUTOHSCROLL defined for the rich edit control) caused setParaFormat to ignore me trying to center the text. After I disabled it and manually set the size of the drawable text area, I was able to center the text. Just in case anyone is curious, here's the code I used to set the width of the drawable area in the rich edit box:
CDC* pDC = GetDC();
long lw = 99999999;
SetTargetDevice(*GetDC(), lw);
I just set lw arbitrarily large so I could test to see if centering the text worked. It did not. As it turns out, when the rich edit control centers the text, it bases it off the draw width of the text, not off the number of characters. I assumed that since there were the same number of characters on either side of the query string then that would cause the string to be centered, but this was not the case.
The final solution I tried was the one suggested by ymett. After some tweaking I came up with a function called alignText() that's called after all the text has been inserted into the rich edit control. Here's the function (Note: each line in the control had tabs inserted before this function was called: one at the beginning of the line and one after the query string e.g. "string1-query-string2" becomes "\tstring1-query\t-string2")
void CFormViewConcordanceRichEditCtrl::alignText()
{
long maxSize = 0;
CFont font;
LOGFONT lf = {0};
CHARFORMAT cf = {0};
this->GetDefaultCharFormat(cf);
//convert a CHARFORMAT struct into a LOGFONT struct
if (cf.dwEffects & CFE_BOLD)
lf.lfWeight = FW_BOLD;
else
lf.lfWeight = FW_NORMAL;
if (cf.dwEffects & CFE_ITALIC)
lf.lfItalic = true;
if (cf.dwEffects & CFE_UNDERLINE)
lf.lfUnderline = true;
if (cf.dwEffects & CFE_STRIKEOUT)
lf.lfStrikeOut = true;
lf.lfHeight = cf.yHeight;
_stprintf(lf.lfFaceName, _T("%s"), cf.szFaceName);
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
font.CreateFontIndirect(&lf);
//create a display context
CClientDC dc(this);
dc.SetMapMode(MM_TWIPS);
CFont *pOldFont = dc.SelectObject(&font);
//find the line that as the longest preceding string when drawn
for(int i = 0; i < m_pParent->m_nDataArray; i++)
{
CString text = m_pParent->DataArray[i].text.Left(BUFFER_LENGTH + m_pParent->generateText.GetLength());
text.Replace(_T("\r"), _T(" "));
text.Replace(_T("\n"), _T(" "));
text.Replace(_T("\t"), _T(" "));
CRect rc(0,0,0,0);
dc.DrawText(text, &rc, DT_CALCRECT);
int width = 1.0*cf.yHeight/fabs((double)rc.bottom - rc.top)*(rc.right - rc.left);
width = dc.GetTextExtent(text).cx;
if(width > maxSize)
maxSize = width;
}
dc.SelectObject(pOldFont);
//this calulates where to place the first tab. The 0.8 is a rought constant calculated by guess & check, it may be innacurate.
long tab = maxSize*0.8;
PARAFORMAT pf;
pf.cbSize = sizeof(PARAFORMAT);
pf.dwMask = PFM_TABSTOPS;
pf.cTabCount = 2;
pf.rgxTabs[0] = tab + (2 << 24); //make the first tab right-aligned
pf.rgxTabs[1] = tab + 25;
//this is to preserve the user's selection and scroll positions when the selection is changed
int vScroll = GetScrollPos(SB_VERT);
int hScroll = GetScrollPos(SB_HORZ);
long spos, epos;
GetSel(spos, epos);
//select all the text
SetSel(0, -1);
//this call is very important, but I'm not sure why
::SendMessage(GetSafeHwnd(), EM_SETTYPOGRAPHYOPTIONS, TO_ADVANCEDTYPOGRAPHY, TO_ADVANCEDTYPOGRAPHY);
this->SetParaFormat(pf);
//now reset the user's selection and scroll positions
SetSel(spos, epos);
::SendMessage(GetSafeHwnd(),
WM_HSCROLL,
(WPARAM) ((hScroll) << 16) + SB_THUMBPOSITION,
(LPARAM) NULL);
::SendMessage(GetSafeHwnd(),
WM_VSCROLL,
(WPARAM) ((vScroll) << 16) + SB_THUMBPOSITION,
(LPARAM) NULL);
}
Essentially what this function does is make the first tab stop right-aligned and set it at some point x to the right in the control. It then makes the second tab stop a small distance to the right of that, and makes it left-aligned. So all the text from the beginning of each line to the end of the query string (from the first \t to the second \t) is pushed toward the right against the first tab stop, and all the remaining text is pushed toward the left against the second tab stop, causing the query string to be aligned between all the lines in the control. The first part of the function finds out x (by finding out how long each line will be drawn and taking the max) and the second part sets the tab stops.
Thanks again to ymett for the solution.