vector<string> fullJustify(vector<string> &words, int L) { vector<string> lines; vector<string> wordsInLine; int num = static_cast<int>(words.size()); int wordCnt = 0; int wordLen = 0; for (int i = 0; i < num; ++i) { string word = words[i]; // could we add this word into the current line? if (wordLen + word.size() + wordCnt <= L) { wordLen += word.size(); ++wordCnt; wordsInLine.push_back(word); } else { lines.push_back(justifyLine(wordsInLine, L, false)); wordsInLine.clear(); wordsInLine.push_back(word); wordLen = word.size(); wordCnt = 1; } } lines.push_back(justifyLine(wordsInLine, L, true)); return lines; }
vector<string> fullJustify(vector<string>& words, int maxWidth) { if(words.size() == 0) return words; int left = 0, width = -1; vector<string> res; for(int i = 0; i < words.size(); ++i) { width = width + 1 + words[i].size(); if(width <= maxWidth) continue; justifyLine(res, words, left, i-1, width-1-words[i].size(), maxWidth); left = i; width = -1; i--; } string out; while(left != words.size()) { out += words[left]; if(out.size() < maxWidth) out += " "; left++; } while(out.size() != maxWidth) { out += " "; } res.push_back(out); return res; }
void GlyphSet::lineWrap(Shaping &shaping, const float lineHeight, const float maxWidth, const float horizontalAlign, const float verticalAlign, const float justify, const Point<float> &translate) const { uint32_t lastSafeBreak = 0; uint32_t lengthBeforeCurrentLine = 0; uint32_t lineStartIndex = 0; uint32_t line = 0; uint32_t maxLineLength = 0; std::vector<PositionedGlyph> &positionedGlyphs = shaping.positionedGlyphs; if (maxWidth) { for (uint32_t i = 0; i < positionedGlyphs.size(); i++) { PositionedGlyph &shape = positionedGlyphs[i]; shape.x -= lengthBeforeCurrentLine; shape.y += lineHeight * line; if (shape.x > maxWidth && lastSafeBreak > 0) { uint32_t lineLength = positionedGlyphs[lastSafeBreak + 1].x; maxLineLength = util::max(lineLength, maxLineLength); for (uint32_t k = lastSafeBreak + 1; k <= i; k++) { positionedGlyphs[k].y += lineHeight; positionedGlyphs[k].x -= lineLength; } if (justify) { // Collapse invisible characters. uint32_t breakGlyph = positionedGlyphs[lastSafeBreak].glyph; uint32_t lineEnd = lastSafeBreak; if (breakGlyph == 0x20 /* space */ || breakGlyph == 0x200b /* zero-width space */) { lineEnd--; } justifyLine(positionedGlyphs, sdfs, lineStartIndex, lineEnd, justify); } lineStartIndex = lastSafeBreak + 1; lastSafeBreak = 0; lengthBeforeCurrentLine += lineLength; line++; } // Spaces, plus word-breaking punctuation that often appears without surrounding spaces. if (shape.glyph == 0x20 /* space */ || shape.glyph == 0x26 /* ampersand */ || shape.glyph == 0x2b /* plus sign */ || shape.glyph == 0x2d /* hyphen-minus */ || shape.glyph == 0x2f /* solidus */ || shape.glyph == 0xad /* soft hyphen */ || shape.glyph == 0xb7 /* middle dot */ || shape.glyph == 0x200b /* zero-width space */ || shape.glyph == 0x2010 /* hyphen */ || shape.glyph == 0x2013 /* en dash */) { lastSafeBreak = i; } } } const PositionedGlyph& lastPositionedGlyph = positionedGlyphs.back(); const auto lastGlyphIt = sdfs.find(lastPositionedGlyph.glyph); assert(lastGlyphIt != sdfs.end()); const uint32_t lastLineLength = lastPositionedGlyph.x + lastGlyphIt->second.metrics.advance; maxLineLength = std::max(maxLineLength, lastLineLength); const uint32_t height = (line + 1) * lineHeight; justifyLine(positionedGlyphs, sdfs, lineStartIndex, uint32_t(positionedGlyphs.size()) - 1, justify); align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line, translate); // Calculate the bounding box shaping.top += -verticalAlign * height; shaping.bottom = shaping.top + height; shaping.left += -horizontalAlign * maxLineLength; shaping.right = shaping.left + maxLineLength; }
void FontStack::lineWrap(Shaping &shaping, const float lineHeight, const float maxWidth, const float horizontalAlign, const float verticalAlign, const float justify) const { uint32_t lastSafeBreak = 0; uint32_t lengthBeforeCurrentLine = 0; uint32_t lineStartIndex = 0; uint32_t line = 0; uint32_t maxLineLength = 0; std::vector<PositionedGlyph> &positionedGlyphs = shaping.positionedGlyphs; if (maxWidth) { for (uint32_t i = 0; i < positionedGlyphs.size(); i++) { PositionedGlyph &shape = positionedGlyphs[i]; shape.x -= lengthBeforeCurrentLine; shape.y += lineHeight * line; if (shape.x > maxWidth && lastSafeBreak > 0) { uint32_t lineLength = positionedGlyphs[lastSafeBreak + 1].x; maxLineLength = util::max(lineLength, maxLineLength); for (uint32_t k = lastSafeBreak + 1; k <= i; k++) { positionedGlyphs[k].y += lineHeight; positionedGlyphs[k].x -= lineLength; } if (justify) { justifyLine(positionedGlyphs, metrics, lineStartIndex, lastSafeBreak - 1, justify); } lineStartIndex = lastSafeBreak + 1; lastSafeBreak = 0; lengthBeforeCurrentLine += lineLength; line++; } if (shape.glyph == 32) { lastSafeBreak = i; } } } const PositionedGlyph& lastPositionedGlyph = positionedGlyphs.back(); const auto lastGlyphMetric = metrics.find(lastPositionedGlyph.glyph); assert(lastGlyphMetric != metrics.end()); const uint32_t lastLineLength = lastPositionedGlyph.x + lastGlyphMetric->second.advance; maxLineLength = std::max(maxLineLength, lastLineLength); const uint32_t height = (line + 1) * lineHeight; justifyLine(positionedGlyphs, metrics, lineStartIndex, uint32_t(positionedGlyphs.size()) - 1, justify); align(shaping, justify, horizontalAlign, verticalAlign, maxLineLength, lineHeight, line); // Calculate the bounding box shaping.top += -verticalAlign * height; shaping.bottom = shaping.top + height; shaping.left += -horizontalAlign * maxLineLength; shaping.right = shaping.left + maxLineLength; }