void CliArguments::displayUseInstructions() { QList<LineElement> list; QString argName; QVariant argValue; QString execName = QString(QCoreApplication::argv()[0]); int maxlen = 0; for (auto it = m_arguments.begin(); it != m_arguments.end(); it++) { argName = ""; argValue = it.value().value; if (it.value().shortTag) { argName = " -" + QString(it.value().shortTag) + (argValue.type() == QVariant::String ? " <" + tr("value") + "> or" : " or"); } argName += " --" + it.value().name + (argValue.type() == QVariant::String ? "=<" + tr("value") + ">" : ""); maxlen = qMax(maxlen, argName.length()); list.append(LineElement(argName, it.value().description + (argValue.type() == QVariant::String ? " (" + tr("value: ") + argValue.toString() + ")" : ""))); } cout << tr("Use: ") << execName << tr(" <options>") << endl << endl << tr("Option list:") << endl; foreach(LineElement pair, list) { cout << pair.first << QString(maxlen - pair.first.length() + 4, ' ') << pair.second << endl; }
const vector<StyledLine> ofxFontStash2::layoutLines(const vector<StyledText> &blocks, float targetWidth, bool debug ){ float x = 0; float y = 0; if (targetWidth < 0) return vector<StyledLine>(); float xx = x; float yy = y; TS_START_NIF("split words"); vector<SplitTextBlock> words = splitWords(blocks); TS_STOP_NIF("split words"); if (words.size() == 0) return vector<StyledLine>(); vector<StyledLine> lines; // here we create the first line. a few things to note: // - in general, like in a texteditor, the line exists first, then content is added to it. // - 'line' here refers to the visual representation. even a line with no newline (\n) can span multiple lines lines.push_back(StyledLine()); ofxFontStashStyle currentStyle; currentStyle.fontSize = -1; // this makes sure the first style is actually applied, even if it's the default style float lineWidth = 0; int wordsThisLine = 0; vector<float> lineHeigts; float currentLineH = 0; float bounds[4]; float dx; LineElement le; TS_START("walk words"); for(int i = 0; i < words.size(); i++){ StyledLine ¤tLine = lines.back(); //TS_START_ACC("word style"); if(words[i].styledText.style.valid && currentStyle != words[i].styledText.style ){ //cout << " new style!" << endl; currentStyle = words[i].styledText.style; if(applyStyle(currentStyle)){ fonsVertMetrics(fs, NULL, NULL, ¤tLineH); currentLineH/=pixelDensity; }else{ ofLogError() << "no style font defined!"; } } //TS_STOP_ACC("word style"); bool stayOnCurrentLine = true; if( words[i].type == SEPARATOR_INVISIBLE && words[i].styledText.text == "\n" ){ stayOnCurrentLine = false; dx = 0; // add a zero-width enter mark. this is used to keep track // of the vertical spacing of empty lines. le = LineElement(words[i], ofRectangle(xx,yy,0,currentLineH)); le.baseLineY = yy; le.x = xx; le.lineHeight = currentLineH; currentLine.elements.push_back(le); float lineH = calcLineHeight(currentLine); currentLine.lineH = lineH; currentLine.lineW = xx - x + dx; // no! //i--; //re-calc dimensions of this word on a new line! yy += lineH; lineWidth = 0; wordsThisLine = 0; xx = x; lines.push_back(StyledLine()); continue; } else{ //TS_START_ACC("fonsTextBounds"); // applyStyle() already upscaled the font size for the display resolution. // Here we do the same for x/y. // The result gets the inverse treatment. dx = fonsTextBounds( fs, xx*pixelDensity, yy*pixelDensity, words[i].styledText.text.c_str(), NULL, &bounds[0] )/pixelDensity; bounds[0]/=pixelDensity; bounds[1]/=pixelDensity; bounds[2]/=pixelDensity; bounds[3]/=pixelDensity; //TS_STOP_ACC("fonsTextBounds"); //hansi: using dx instead of bounds[2]-bounds[0] //dx is the right size for spacing out text. bounds give exact area of the char, which isn't so useful here. ofRectangle where = ofRectangle(bounds[0], bounds[1] , dx, bounds[3] - bounds[1]); le = LineElement(words[i], where); le.baseLineY = yy; le.x = xx; le.lineHeight = currentLineH; float nextWidth = lineWidth + dx; //if not wider than targetW // || //this is the 1st word in this line but even that doesnt fit stayOnCurrentLine = nextWidth < targetWidth || (wordsThisLine == 0 && (nextWidth >= targetWidth)); } if (stayOnCurrentLine){ //TS_START_ACC("stay on line"); currentLine.elements.push_back(le); lineWidth += dx; xx += dx; wordsThisLine++; //TS_STOP_ACC("stay on line"); } else if( words[i].type == SEPARATOR_INVISIBLE && words[i].styledText.text == " " ){ // ignore spaces when moving into the next line! continue; } else{ //too long, start a new line //TS_START_ACC("new line"); //calc height for this line - taking in account all words in the line float lineH = lineHeightMultiplier * calcLineHeight(currentLine); currentLine.lineH = lineH; currentLine.lineW = xx - x; i--; //re-calc dimensions of this word on a new line! yy += lineH; lineWidth = 0; wordsThisLine = 0; xx = x; lines.push_back(StyledLine()); //TS_STOP_ACC("new line"); } } //TS_START_ACC("last line"); // update dimensions of the last line StyledLine ¤tLine = lines.back(); if( currentLine.elements.size() == 0 ){ // but at least one spacing character, so we have a line height. le = LineElement(SplitTextBlock(SEPARATOR_INVISIBLE,"",currentStyle), ofRectangle(xx,yy,0,currentLineH)); le.baseLineY = yy; le.x = xx; le.lineHeight = currentLineH; currentLine.elements.push_back(le); } float lineH = calcLineHeight(currentLine); currentLine.lineH = lineH; currentLine.lineW = xx - x + dx; //TS_STOP_ACC("last line"); TS_STOP("walk words"); return lines; }