void TextSpan::DrawContentsInRegions(const Regions& rgns, const Point& offset) const { size_t charsPrinted = 0; Regions::const_iterator rit = rgns.begin(); for (; rit != rgns.end(); ++rit) { Region drawRect = *rit; drawRect.x += offset.x; drawRect.y += offset.y; const Font* printFont = font; Palette* printPalette = palette; TextContainer* container = dynamic_cast<TextContainer*>(parent); if (printFont == NULL && container) { printFont = container->TextFont(); } if (printPalette == NULL && container) { printPalette = container->TextPalette(); } assert(printFont && printPalette); #if (DEBUG_TEXT) // FIXME: this shouldnt happen, but it does (BG2 belt03 unidentified). // for now only assert when DEBUG_TEXT is set // the situation is benign and nothing even looks wrong because all that this means is that there was more space allocated than was actually needed assert(charsPrinted < text.length()); core->GetVideoDriver()->DrawRect(drawRect, ColorRed, true); #endif charsPrinted += printFont->Print(drawRect, text.substr(charsPrinted), printPalette, IE_FONT_ALIGN_LEFT); #if (DEBUG_TEXT) core->GetVideoDriver()->DrawRect(drawRect, ColorWhite, false); #endif } }
bool borderVAny( const Regions& rs, mfxU32 i,mfxU32 j ) { bool ret = false; Regions::const_iterator it = rs.begin(); while(!ret && it != rs.end() ) ret = (it++)->onBorderV(i,j); return ret; }
std::pair<bool, std::string> insideAny( const Regions& rs, mfxU32 i,mfxU32 j ) { std::pair<bool, std::string> ret = std::make_pair( false, std::string("") ); Regions::const_iterator it = rs.begin(); while(!ret.first && it != rs.end() ) { if( it->inside(i,j) ) ret = std::make_pair( true, it->m_name ); ++it; } return ret; }
Regions TextSpan::LayoutForPointInRegion(Point layoutPoint, const Region& rgn) const { Regions layoutRegions; const Point& drawOrigin = rgn.Origin(); const Font* layoutFont = LayoutFont(); assert(layoutFont); if (frame.Dimensions().IsZero()) { // this means we get to wrap :) // calculate each line and print line by line int lineheight = layoutFont->LineHeight; Regions lineExclusions; Region lineRgn(layoutPoint + drawOrigin, Size(rgn.w, lineheight)); lineRgn.y -= lineheight; Region lineSegment; #define LINE_REMAINDER lineRgn.w - lineSegment.x; const Region* excluded = NULL; size_t numPrinted = 0; bool newline = true; do { if (newline || lineSegment.x + lineSegment.w >= lineRgn.x + lineRgn.w) { // start next line newline = false; lineRgn.x = drawOrigin.x; lineRgn.y += lineheight; lineRgn.w = rgn.w; layoutPoint = lineRgn.Origin(); lineSegment = lineRgn; } do { // process all overlaping exclusion zones until we trim down to the leftmost non conflicting region. // check for intersections with other content excluded = parent->ContentRegionForRect(lineSegment); if (!excluded) { // now check if we already used this region ourselves std::vector<Region>::const_iterator it; for (it = lineExclusions.begin(); it != lineExclusions.end(); ++it) { if (lineSegment.IntersectsRegion(*it)) { excluded = &*it; break; } } } // no else! if (excluded) { Region intersect = excluded->Intersect(lineSegment); if (intersect.x > lineSegment.x) { // to the right, simply shrink the width lineSegment.w = intersect.x - lineSegment.x; } else { // overlaps our start point, jump to the right of intersect int x = lineSegment.x; lineSegment.x = intersect.x + intersect.w; // must shrink to compensate for moving x lineSegment.w -= lineSegment.x - x; } // its possible that the resulting segment is 0 in width if (lineSegment.w <= 0) { lineSegment.x = intersect.x + intersect.w; lineSegment.w = LINE_REMAINDER; lineExclusions.push_back(lineSegment); newline = true; goto newline; } } } while (excluded); { // protected scope for goto assert(lineSegment.h == lineheight); size_t numOnLine = 0; // must limit our operation to this single line. size_t nextLine = text.find_first_of(L'\n', numPrinted); if (nextLine == numPrinted) { // this is a new line, we dont have to actually size that // simply occupy the entire area and advance. lineSegment.w = LINE_REMAINDER; numOnLine = 1; newline = true; } else { size_t subLen = nextLine; if (nextLine != String::npos) { subLen = nextLine - numPrinted + 1; // +1 for the \n } const String& substr = text.substr(numPrinted, subLen); Font::StringSizeMetrics metrics = {lineSegment.Dimensions(), 0, lineSegment.w == lineRgn.w}; Size printSize = layoutFont->StringSize(substr, &metrics); numOnLine = metrics.numChars; assert(numOnLine || !metrics.forceBreak); bool noFit = !metrics.forceBreak && numOnLine == 0; bool lineFilled = lineSegment.x + lineSegment.w == lineRgn.w; bool moreChars = numPrinted + numOnLine < text.length(); if (subLen != String::npos || noFit || (lineFilled && moreChars)) { // optimization for when the segment is the entire line (and we have more text) // saves looping again for the known to be useless segment newline = true; lineSegment.w = LINE_REMAINDER; } else { assert(printSize.w); lineSegment.w = printSize.w; } } numPrinted += numOnLine; } assert(!lineSegment.Dimensions().IsEmpty()); lineExclusions.push_back(lineSegment); newline: if (newline || numPrinted == text.length()) { // must claim the lineExclusions as part of the layout // just because we didnt fit doesnt mean somethng else wont... Region lineLayout = Region::RegionEnclosingRegions(lineExclusions); assert(lineLayout.h % lineheight == 0); layoutRegions.push_back(lineLayout); lineExclusions.clear(); } // FIXME: infinite loop possibility. } while (numPrinted < text.length()); #undef LINE_REMAINDER assert(numPrinted == text.length()); } else { // we are limited to drawing within our frame :( // FIXME: we ought to be able to set an alignment for "blocks" of text // probably the way to do this is have alignment on the container // then maybe another Draw method that takes an alignment argument? Region drawRegion = LayoutInFrameAtPoint(layoutPoint, rgn); assert(drawRegion.h && drawRegion.w); layoutRegions.push_back(drawRegion); } return layoutRegions; }
void cairo_regions(cairo_t *cr, Regions const &p) { srand(0); for(Regions::const_iterator j = p.begin(); j != p.end(); ++j) cairo_region(cr, *j); }