// Finds the intersection of the ordered region lists, stores in dest void EffectTruncSilence::Intersect(RegionList &dest, const RegionList &src) { RegionList::iterator destIter; destIter = dest.begin(); // Any time we reach the end of the dest list we're finished if (destIter == dest.end()) return; RegionList::iterator curDest = destIter; // Operation: find non-silent regions in src, remove them from dest. double nsStart = curDest->start; double nsEnd; bool lastRun = false; // must run the loop one extra time RegionList::const_iterator srcIter = src.begin(); // This logic, causing the loop to run once after end of src, must occur // each time srcIter is updated if (srcIter == src.end()) { lastRun = true; } while (srcIter != src.end() || lastRun) { // Don't use curSrc unless lastRun is false! RegionList::const_iterator curSrc; if (lastRun) { // The last non-silent region extends as far as possible nsEnd = std::numeric_limits<double>::max(); } else { curSrc = srcIter; nsEnd = curSrc->start; } if (nsEnd > nsStart) { // Increment through dest until we have a region that could be affected while (curDest->end <= nsStart) { ++destIter; if (destIter == dest.end()) { return; } curDest = destIter; } // Check for splitting dest region in two if (nsStart > curDest->start && nsEnd < curDest->end) { // The second region Region r(nsEnd, curDest->end); // The first region curDest->end = nsStart; // Insert second region after first RegionList::iterator nextIt(destIter); ++nextIt; // This should just read: destIter = dest.insert(nextIt, r); but we // work around two two wxList::insert() bugs. First, in some // versions it returns the wrong value. Second, in some versions, // it crashes when you insert at list end. if (nextIt == dest.end()) dest.push_back(r); else dest.insert(nextIt, r); ++destIter; // (now points at the newly-inserted region) curDest = destIter; } // Check for truncating the end of dest region if (nsStart > curDest->start && nsStart < curDest->end && nsEnd >= curDest->end) { curDest->end = nsStart; ++destIter; if (destIter == dest.end()) { return; } curDest = destIter; } // Check for all dest regions that need to be removed completely while (nsStart <= curDest->start && nsEnd >= curDest->end) { destIter = dest.erase(destIter); if (destIter == dest.end()) { return; } curDest = destIter; } // Check for truncating the beginning of dest region if (nsStart <= curDest->start && nsEnd > curDest->start && nsEnd < curDest->end) { curDest->start = nsEnd; } } if (lastRun) { // done lastRun = false; } else { // Next non-silent region starts at the end of this silent region nsStart = curSrc->end; ++srcIter; if (srcIter == src.end()) { lastRun = true; } } } }
/** * Gibt Infos, über die Unterbrechungspunkte in einem Text * * @param[in] text Text, der auf Zeilen verteilt werden soll * @param[in] primary_width Maximale Breite der ersten Zeile * @param[in] secondary_width Maximale Breite der weiteren Zeilen */ glArchivItem_Font::WrapInfo glArchivItem_Font::GetWrapInfo(const std::string& text, const unsigned short primary_width, const unsigned short secondary_width) { if(!fontNoOutline) initFont(); RTTR_Assert(isValidUTF8(text)); // Can only handle UTF-8 strings! // Current line width unsigned line_width = 0; // Width of current word unsigned word_width = 0; unsigned curMaxLineWidth = primary_width; WrapInfo wi; // We start the first line at the first char (so wi.positions.size() == numLines) wi.positions.push_back(0); utf8Iterator it(text.begin(), text.begin(), text.end()); utf8Iterator itEnd(text.end(), text.begin(), text.end()); utf8Iterator itWordStart = it; const unsigned spaceWidth = CharWidth(' '); for(;; ++it) { uint32_t curChar = (it != itEnd) ? *it : 0; // Word ended if(curChar == 0 || curChar == '\n' || curChar == ' ') { // Is the current word to long for the current line if(word_width + line_width > curMaxLineWidth) { // Word does not fit -> Start new line // Can we fit the word in one line? if(word_width <= secondary_width) { // New line starts at index of word start wi.positions.push_back(static_cast<unsigned>(itWordStart.base() - text.begin())); line_width = 0; } else { // Word does not even fit on one line -> Put as many letters in one line as possible for(utf8Iterator itWord = itWordStart; itWord != it; ++itWord) { unsigned letter_width = CharWidth(*itWord); // Can we fit the letter onto current line? if(line_width + letter_width <= curMaxLineWidth) line_width += letter_width; // Add it else { // Create new line at this letter wi.positions.push_back(static_cast<unsigned>(itWord.base() - text.begin())); line_width = letter_width; itWordStart = nextIt(itWord); } } // Restart word word_width = 0; } curMaxLineWidth = secondary_width; } if(curChar == 0) break; else if(curChar == ' ') { // Set up this line if we are going to continue it (not at line break or text end) // Line contains word and whitespace line_width += word_width + spaceWidth; word_width = 0; itWordStart = nextIt(it); } else { // If line break add new line (after all the word-breaking above) itWordStart = nextIt(it); if(itWordStart == itEnd) break; // Reached end word_width = 0; line_width = 0; wi.positions.push_back(static_cast<unsigned>(itWordStart.base() - text.begin())); } } else { // Some char -> Add its width word_width += CharWidth(curChar); } } // Ignore trailing newline if(wi.positions.back() + 1 >= text.length() && wi.positions.size() > 1) wi.positions.pop_back(); return wi; }