Json::Value
PendingEnvelopes::getJsonInfo(size_t limit)
{
    Json::Value ret;

    updateMetrics();

    {
        auto it = mEnvelopes.rbegin();
        size_t l = limit;
        while (it != mEnvelopes.rend() && l-- != 0)
        {
            if (it->second.mFetchingEnvelopes.size() != 0)
            {
                Json::Value& slot = ret[std::to_string(it->first)]["fetching"];
                for (auto const& e : it->second.mFetchingEnvelopes)
                {
                    slot.append(mHerder.getSCP().envToStr(e));
                }
            }
            if (it->second.mReadyEnvelopes.size() != 0)
            {
                Json::Value& slot = ret[std::to_string(it->first)]["pending"];
                for (auto const& e : it->second.mReadyEnvelopes)
                {
                    slot.append(mHerder.getSCP().envToStr(e));
                }
            }
            it++;
        }
    }
    return ret;
}
Example #2
0
//sets the new positon to the given values, informs all other objects about the collision if needed, updates the grid
void Field::updatePosition(const float &xNew, const float &yNew)
{
	if (x != xNew || y != yNew) {
		updateMetrics(metrics, affectedGrids, (int32_t)xNew, (int32_t)yNew);

		applyCollision();

		int32_t newGridX = (int32_t)floor(xNew / GRID_SIZE);
		int32_t newGridY = (int32_t)floor(yNew / GRID_SIZE);

		if (xGridded != newGridX || yGridded != newGridY)
		{
			removeFromMap();

			x = xNew;
			y = yNew;
	
			xGridded = newGridX;
			yGridded = newGridY;

			insertIntoMap();
		}
		else
		{
			x = xNew;
			y = yNew;
	
			xGridded = newGridX;
			yGridded = newGridY;
		}
	}
}
void
PendingEnvelopes::discardSCPEnvelope(SCPEnvelope const& envelope)
{
    try
    {
        if (isDiscarded(envelope))
        {
            return;
        }

        auto& discardedSet =
            mEnvelopes[envelope.statement.slotIndex].mDiscardedEnvelopes;
        discardedSet.insert(envelope);

        auto& fetchingSet =
            mEnvelopes[envelope.statement.slotIndex].mFetchingEnvelopes;
        fetchingSet.erase(envelope);

        stopFetch(envelope);
        updateMetrics();
    }
    catch (xdr::xdr_runtime_error& e)
    {
        CLOG(TRACE, "Herder")
            << "PendingEnvelopes::discardSCPEnvelope got corrupt message: "
            << e.what();
    }
}
Example #4
0
void Field::init(const int32_t &x, const int32_t &y, const int32_t &metricsLength, const int32_t &affectedGridsLength)
{
	this->x = (float)x;
	this->y = (float)y;
	
	xGridded = (int32_t)floor(this->x / GRID_SIZE);
	yGridded = (int32_t)floor(this->y / GRID_SIZE);

	liquid = false;

	swimming = false;
	grounded = false;

	this->metricsLength = metricsLength;
	metrics = new Rect[metricsLength];
	metricsNew = new Rect[metricsLength];

	this->affectedGridsLength = affectedGridsLength;
	affectedGrids = new int64_t[affectedGridsLength];
	affectedGridsNew = new int64_t[affectedGridsLength];

	updateMetrics(metrics, affectedGrids, x, y);

	insertIntoMap();
	
	appropriateTool = Default;
	health = (float)1.1;
}
Example #5
0
	void ListCtrl::updateFromResize()
	{
		updateMetrics();

		updateScrollSize();
		updateScrollPosition();

		_updateAllVisible(ITEM_NONE, true, true);
		_resetContainer(true);
	}
void
PendingEnvelopes::discardSCPEnvelopesWithQSet(Hash hash)
{
    CLOG(TRACE, "Herder") << "Discarding SCP Envelopes with SCPQSet "
                          << hexAbbrev(hash);

    auto envelopes = mQuorumSetFetcher.fetchingFor(hash);
    for (auto& envelope : envelopes)
        discardSCPEnvelope(envelope);

    updateMetrics();
}
Example #7
0
	ItemBox::ItemBox(const IntCoord& _coord, char _align, const WidgetSkinInfoPtr _info, CroppedRectanglePtr _parent, const Ogre::String & _name) :
		Widget(_coord, _align, _info, _parent, _name),
		mWidgetScroll(null),
		mWidgetClient(null),
		mTopIndex(0),
		mOffsetTop(0),
		mRangeIndex(-1),
		//mLastRedrawLine(0),
		//mIndexSelect(ITEM_NONE),
		mIsFocus(false),
		mCountItems(0)
	{
		// нам нужен фокус клавы
		mNeedKeyFocus = true;

		for (VectorWidgetPtr::iterator iter=mWidgetChild.begin(); iter!=mWidgetChild.end(); ++iter) {
			if ((*iter)->_getInternalString() == "VScroll") {
				mWidgetScroll = castWidget<VScroll>(*iter);
				mWidgetScroll->eventScrollChangePosition = newDelegate(this, &ItemBox::notifyScrollChangePosition);
				//mWidgetScroll->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMousePressed);
			}
			else if ((*iter)->_getInternalString() == "Client") {
				mWidgetClient = (*iter);
				//mWidgetClient->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMousePressed);
				mWidgetClient->eventMouseWheel = newDelegate(this, &ItemBox::notifyMouseWheel);
			}
		}
		MYGUI_ASSERT(null != mWidgetScroll, "Child VScroll not found in skin (ItemBox must have VScroll)");
		MYGUI_ASSERT(null != mWidgetClient, "Child Widget Client not found in skin (ItemBox must have Client)");

		// парсим свойства
		/*const MapString & param = _info->getParams();
		MapString::const_iterator iter = param.find("SkinLine");
		if (iter != param.end()) mSkinLine = iter->second;
		MYGUI_ASSERT(false == mSkinLine.empty(), "SkinLine property or skin not found (ItemBox must have SkinLine property)");

		iter = param.find("HeightLine");
		if (iter != param.end()) mHeightLine = utility::parseInt(iter->second);
		if (mHeightLine < 1) mHeightLine = 1;

*/
		mWidgetScroll->setScrollPage((size_t)mSizeItem.height);

		mSizeItem.set(50, 50);
		mCountItems = 200;

		updateMetrics();
		updateScroll();
		_redrawAllVisible();
		//updateLine();

	}
Example #8
0
	void ItemBox::updateFromResize(const IntSize& _size)
	{
		int old_count = mCountItemInLine;
		updateMetrics();
		updateScroll();

		// если колличество айтемов в строке изменилось, то перерисовываем все
		if (old_count == mCountItemInLine) {
			// если строк стало меньшн то ничего не нужно
			if (_size.height >= mCoord.height) return;
		}

		notifyScrollChangePosition(null, mWidgetScroll->getScrollPosition());
		_redrawAllVisible();
	}
void
PendingEnvelopes::eraseBelow(uint64 slotIndex)
{
    for (auto iter = mEnvelopes.begin(); iter != mEnvelopes.end();)
    {
        if (iter->first < slotIndex)
        {
            iter = mEnvelopes.erase(iter);
        }
        else
            break;
    }

    // 0 is special mark for data that we do not know the slot index
    // it is used for state loaded from database
    mTxSetCache.erase_if([&](TxSetFramCacheItem const& i) {
        return i.first != 0 && i.first < slotIndex;
    });

    updateMetrics();
}
Example #10
0
void
PendingEnvelopes::slotClosed(uint64 slotIndex)
{
    // force recomputing the quorums
    mNodesInQuorum.clear();

    // stop processing envelopes & downloads for the slot falling off the
    // window
    if (slotIndex > Herder::MAX_SLOTS_TO_REMEMBER)
    {
        slotIndex -= Herder::MAX_SLOTS_TO_REMEMBER;

        mEnvelopes.erase(slotIndex);

        mTxSetFetcher.stopFetchingBelow(slotIndex + 1);
        mQuorumSetFetcher.stopFetchingBelow(slotIndex + 1);

        mTxSetCache.erase_if(
            [&](TxSetFramCacheItem const& i) { return i.first == slotIndex; });
    }

    updateMetrics();
}
Example #11
0
	void ItemBox::eraseContent()
	{
		updateMetrics();
	}
Example #12
0
//TODO this just is a stub right now, it only sets the vector to 0 on collision
//shortens a movment vector so it only colides, but does not intersect, with other objects
void Field::applyCollisionToVector(Vector2 &moveVector)
{
	int64_t xy64;
	unordered_map<int64_t, FieldBack*>::const_iterator backIt;
	pair<unordered_multimap<int64_t, FieldFront*>::iterator, unordered_multimap<int64_t, FieldFront*>::iterator> frontItPair;
	unordered_multimap<int64_t, FieldFront*>::iterator frontIt;

	int32_t i;
	int32_t ii;
	int32_t ai;

	updateMetrics(metricsNew, affectedGridsNew, (int32_t)(this->x + moveVector.x), (int32_t)(this->y + moveVector.y));

	for (ai = 0; ai<affectedGridsLength; ai++)
	{
		xy64 = affectedGridsNew[ai];

		backIt = world.mapBack.find(xy64);
		if (backIt != world.mapBack.end())
		{
			if (backIt->second != NULL && backIt->second != this && (colidingLayer !=3 || backIt->second->colidingLayer == 2) && !backIt->second->liquid) //TODO prevent double checking the same object!
			{
				for (i = 0; i<metricsLength; i++)
				{
					for (ii = 0; ii<backIt->second->metricsLength; ii++)
					{
						if (metricsNew[i].intersectsWith(backIt->second->metrics[ii]))
						{
							if (metricsNew[i].shortenVectorToNotInteresctWith(backIt->second->metrics[ii], moveVector))
							{
								return applyCollisionToVector(moveVector);
							}
							else
							{
								return;
							}
						}
					}
				}
			}
		}

		if (colidingLayer != 1)
		{
			frontItPair = world.mapFront.equal_range(xy64);

			for (frontIt=frontItPair.first; frontIt!=frontItPair.second; ++frontIt)
			{
				if (frontIt->second != NULL && frontIt->second != this) //TODO prevent double checking the same object!
				{
					for (i = 0; i<metricsLength; i++)
					{
						for (ii = 0; ii<frontIt->second->metricsLength; ii++)
						{
							if (metricsNew[i].intersectsWith(backIt->second->metrics[ii]))
							{
								if (metricsNew[i].shortenVectorToNotInteresctWith(backIt->second->metrics[ii], moveVector))
								{
									return applyCollisionToVector(moveVector);
								}
								else
								{
									return;
								}
							}
						}
					}
				}
			}
		}
	}
}
Example #13
0
	void ListCtrl::eraseContent()
	{
		_updateAllVisible(ITEM_NONE, false, true);
		updateMetrics();
	}
Example #14
0
void extractCalls(Config *config) {
    bam_hdr_t *hdr = sam_hdr_read(config->fp);
    bam_mplp_t iter;
    int ret, tid, pos, i, seqlen, type, rv, o = 0;
    int beg0 = 0, end0 = 1u<<29;
    int n_plp; //This will need to be modified for multiple input files
    int ctid = -1; //The tid of the contig whose sequence is stored in "seq"
    int idxBED = 0, strand;
    uint32_t nmethyl = 0, nunmethyl = 0;
    const bam_pileup1_t **plp = NULL;
    char *seq = NULL, base;
    mplp_data *data = NULL;
    struct lastCall *lastCpG = NULL;
    struct lastCall *lastCHG = NULL;

    if(config->merge) {
        if(config->keepCpG) {
            lastCpG = calloc(1, sizeof(struct lastCall));
            assert(lastCpG);
            lastCpG->tid = -1;
        }
        if(config->keepCHG) {
            lastCHG = calloc(1, sizeof(struct lastCall));
            assert(lastCHG);
            lastCHG->tid = -1;
        }
    }

    data = calloc(1,sizeof(mplp_data));
    if(data == NULL) {
        fprintf(stderr, "Couldn't allocate space for the data structure in extractCalls()!\n");
        return;
    }
    data->config = config;
    data->hdr = hdr;
    if (config->reg) {
        if((data->iter = sam_itr_querys(config->bai, hdr, config->reg)) == 0) {
            fprintf(stderr, "failed to parse regions %s", config->reg);
            return;
        }
    }
    if(config->bedName) {
        config->bed = parseBED(config->bedName, hdr);
        if(config->bed == NULL) return;
    }

    plp = calloc(1, sizeof(bam_pileup1_t *)); //This will have to be modified for multiple input files
    if(plp == NULL) {
        fprintf(stderr, "Couldn't allocate space for the plp structure in extractCalls()!\n");
        return;
    }

    //Start the pileup
    iter = bam_mplp_init(1, filter_func, (void **) &data);
    bam_mplp_init_overlaps(iter);
    bam_mplp_set_maxcnt(iter, config->maxDepth);
    while((ret = cust_mplp_auto(iter, &tid, &pos, &n_plp, plp)) > 0) {
        //Do we need to process this position?
        if (config->reg) {
            beg0 = data->iter->beg, end0 = data->iter->end;
            if ((pos < beg0 || pos >= end0)) continue; // out of the region requested
        }
        if(tid != ctid) {
            if(seq != NULL) free(seq);
            seq = faidx_fetch_seq(config->fai, hdr->target_name[tid], 0, faidx_seq_len(config->fai, hdr->target_name[tid]), &seqlen);
            if(seqlen < 0) {
                fprintf(stderr, "faidx_fetch_seq returned %i while trying to fetch the sequence for tid %i (%s)!\n",\
                        seqlen, tid, hdr->target_name[tid]);
                fprintf(stderr, "Note that the output will be truncated!\n");
                return;
            }
            ctid = tid;
        }

        if(config->bed) { //Handle -l
            while((o = posOverlapsBED(tid, pos, config->bed, idxBED)) == -1) idxBED++;
            if(o == 0) continue; //Wrong strand
        }

        if(isCpG(seq, pos, seqlen)) {
            if(!config->keepCpG) continue;
            type = 0;
        } else if(isCHG(seq, pos, seqlen)) {
            if(!config->keepCHG) continue;
            type = 1;
        } else if(isCHH(seq, pos, seqlen)) {
            if(!config->keepCHH) continue;
            type = 2;
        } else {
            continue;
        }

        nmethyl = nunmethyl = 0;
        base = *(seq+pos);
        for(i=0; i<n_plp; i++) {
            if(plp[0][i].is_del) continue;
            if(plp[0][i].is_refskip) continue;
            if(config->bed) if(!readStrandOverlapsBED(plp[0][i].b, config->bed->region[idxBED])) continue;
            strand = getStrand((plp[0]+i)->b);
            if(strand & 1) {
                if(base != 'C' && base != 'c') continue;
            } else {
                if(base != 'G' && base != 'g') continue;
            }
            rv = updateMetrics(config, plp[0]+i);
            if(rv > 0) nmethyl++;
            else if(rv<0) nunmethyl++;
        }

        if(nmethyl+nunmethyl==0) continue;
        if(!config->merge || type==2) {
            writeCall(config->output_fp[type], config, hdr->target_name[tid], pos, 1, nmethyl, nunmethyl);
        } else {
            //Merge into per-CpG/CHG metrics
            if(type==0) {
                if(base=='G' || base=='g') pos--;
                processLast(config->output_fp[0], config, lastCpG, hdr, tid, pos, 2, nmethyl, nunmethyl);
            } else {
                if(base=='G' || base=='g') pos-=2;
                processLast(config->output_fp[1], config, lastCHG, hdr, tid, pos, 3, nmethyl, nunmethyl);
            }
        }
    }

    //Don't forget the last CpG/CHG
    if(config->merge) {
        if(config->keepCpG && lastCpG->tid != -1) {
            processLast(config->output_fp[0], config, lastCpG, hdr, tid, pos, 2, nmethyl, nunmethyl);
        }
        if(config->keepCHG && lastCHG->tid != -1) {
            processLast(config->output_fp[1], config, lastCHG, hdr, tid, pos, 3, nmethyl, nunmethyl);
        }
    }

    bam_hdr_destroy(hdr);
    if(data->iter) hts_itr_destroy(data->iter);
    bam_mplp_destroy(iter);
    free(data);
    free(plp);
    if(seq != NULL) free(seq);
}
Example #15
0
void Text::updateFormat() {
	FontResource *fontPtr = lockFontResource();
	BS_ASSERT(fontPtr);

	updateMetrics(*fontPtr);

	_lines.resize(1);
	if (_autoWrap && (uint) _width >= _autoWrapThreshold && _text.size() >= 2) {
		_width = 0;
		uint curLineWidth = 0;
		uint curLineHeight = 0;
		uint curLine = 0;
		uint tempLineWidth = 0;
		uint lastSpace = 0; // we need at least 1 space character to start a new line...
		_lines[0].text = "";
		for (uint i = 0; i < _text.size(); ++i) {
			uint j;
			tempLineWidth = 0;
			lastSpace = 0;
			for (j = i; j < _text.size(); ++j) {
				if ((byte)_text[j] == ' ')
					lastSpace = j;

				const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]);
				tempLineWidth += curCharRect.width();
				tempLineWidth += fontPtr->getGapWidth();

				if ((tempLineWidth >= _autoWrapThreshold) && (lastSpace > 0))
					break;
			}

			if (j == _text.size()) // everything in 1 line.
				lastSpace = _text.size();

			curLineWidth = 0;
			curLineHeight = 0;
			for (j = i; j < lastSpace; ++j) {
				_lines[curLine].text += _text[j];

				const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]);
				curLineWidth += curCharRect.width();
				curLineWidth += fontPtr->getGapWidth();
				if ((uint)curCharRect.height() > curLineHeight)
					curLineHeight = curCharRect.height();
			}

			_lines[curLine].bbox.right = curLineWidth;
			_lines[curLine].bbox.bottom = curLineHeight;
			if ((uint)_width < curLineWidth)
				_width = curLineWidth;

			if (lastSpace < _text.size()) {
				++curLine;
				BS_ASSERT(curLine == _lines.size());
				_lines.resize(curLine + 1);
				_lines[curLine].text = "";
			}

			i = lastSpace;
		}

		// Bounding-Box der einzelnen Zeilen relativ zur ersten festlegen (vor allem zentrieren).
		_height = 0;
		Common::Array<Line>::iterator iter = _lines.begin();
		for (; iter != _lines.end(); ++iter) {
			Common::Rect &bbox = (*iter).bbox;
			bbox.left = (_width - bbox.right) / 2;
			bbox.right = bbox.left + bbox.right;
			bbox.top = (iter - _lines.begin()) * fontPtr->getLineHeight();
			bbox.bottom = bbox.top + bbox.bottom;
			_height += bbox.height();
		}
	} else {
		// Keine automatische Formatierung, also wird der gesamte Text in nur eine Zeile kopiert.
		_lines[0].text = _text;
		_lines[0].bbox = Common::Rect(0, 0, _width, _height);
	}

	fontPtr->release();
}
void FillIn::clearFoodList()
{
    ui.lstResults->clear();
    itemToResult.clear();
    updateMetrics();
}
Example #17
0
// called from Peer and when an Item tracker completes
Herder::EnvelopeStatus
PendingEnvelopes::recvSCPEnvelope(SCPEnvelope const& envelope)
{
    auto const& nodeID = envelope.statement.nodeID;
    if (!isNodeInQuorum(nodeID))
    {
        CLOG(DEBUG, "Herder")
            << "Dropping envelope from "
            << mApp.getConfig().toShortString(nodeID) << " (not in quorum)";
        return Herder::ENVELOPE_STATUS_DISCARDED;
    }

    // did we discard this envelope?
    // do we already have this envelope?
    // do we have the qset
    // do we have the txset

    try
    {
        if (isDiscarded(envelope))
        {
            return Herder::ENVELOPE_STATUS_DISCARDED;
        }

        touchFetchCache(envelope);

        auto& set = mEnvelopes[envelope.statement.slotIndex].mFetchingEnvelopes;
        auto& processedList =
            mEnvelopes[envelope.statement.slotIndex].mProcessedEnvelopes;

        auto fetching = find(set.begin(), set.end(), envelope);

        if (fetching == set.end())
        { // we aren't fetching this envelope
            if (find(processedList.begin(), processedList.end(), envelope) ==
                processedList.end())
            { // we haven't seen this envelope before
                // insert it into the fetching set
                fetching = set.insert(envelope).first;
                startFetch(envelope);
            }
            else
            {
                // we already have this one
                return Herder::ENVELOPE_STATUS_PROCESSED;
            }
        }

        // we are fetching this envelope
        // check if we are done fetching it
        if (isFullyFetched(envelope))
        {
            // move the item from fetching to processed
            processedList.emplace_back(*fetching);
            set.erase(fetching);
            envelopeReady(envelope);
            updateMetrics();
            return Herder::ENVELOPE_STATUS_READY;
        } // else just keep waiting for it to come in

        updateMetrics();
        return Herder::ENVELOPE_STATUS_FETCHING;
    }
    catch (xdr::xdr_runtime_error& e)
    {
        CLOG(TRACE, "Herder")
            << "PendingEnvelopes::recvSCPEnvelope got corrupt message: "
            << e.what();
        return Herder::ENVELOPE_STATUS_DISCARDED;
    }
}
Example #18
0
	void ListCtrl::_updateAllVisible(size_t _index, bool _needUpdateContetntSize, bool _update)
	{

		bool change = false;

		int top = 0;
		size_t widget_index = 0;

		for (size_t index = 0; index < mItemsInfo.size(); ++index)
		{
			ItemDataInfo& info = mItemsInfo[index];

			// айтем сверху не виден
			if ((top + info.size.height) < (mContentPosition.top))
			{
			}
			// айтем снизу и не виден
			else if (top > ((mContentPosition.top) + _getClientWidget()->getHeight()))
			{
			}
			// айтем встрял в видимость
			else
			{
				Widget* item = getItemWidget(widget_index);
				widget_index++;

				if (index == _index || ITEM_NONE == _index)
				{
					item->_setInternalData((size_t)index);

					item->setPosition(-mContentPosition.left, top - (mContentPosition.top));
					item->setVisible(true);

					IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, _update, false);

					IntCoord coord(IntPoint(), info.size);
					requestDrawItem(this, item, data, coord);

					if (info.size != coord.size())
						change = true;

					info.size = coord.size();
					item->setSize(mClient->getWidth()/*mContentSize.width*/, info.size.height);
				}

			}

			top += info.size.height;
		}

		// если виджеты еще есть, то их надо скрыть
		while (widget_index < mVectorItems.size())
		{
			Widget* item = mVectorItems[widget_index];
			widget_index ++;

			item->setVisible(false);
			item->_setInternalData((size_t)ITEM_NONE);
		}

		if (change && _needUpdateContetntSize)
		{
			updateMetrics();

			updateScrollSize();
			updateScrollPosition();
		}
	}
Example #19
0
void Text::updateFormat() {
	FontResource *fontPtr = lockFontResource();
	assert(fontPtr);

	updateMetrics(*fontPtr);

	_lines.resize(1);
	if (_autoWrap && (uint) _width >= _autoWrapThreshold && _text.size() >= 2) {
		_width = 0;
		uint curLineWidth = 0;
		uint curLineHeight = 0;
		uint curLine = 0;
		uint tempLineWidth = 0;
		uint lastSpace = 0; // we need at least 1 space character to start a new line...
		_lines[0].text = "";
		for (uint i = 0; i < _text.size(); ++i) {
			uint j;
			tempLineWidth = 0;
			lastSpace = 0;
			for (j = i; j < _text.size(); ++j) {
				if ((byte)_text[j] == ' ')
					lastSpace = j;

				const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]);
				tempLineWidth += curCharRect.width();
				tempLineWidth += fontPtr->getGapWidth();

				if ((tempLineWidth >= _autoWrapThreshold) && (lastSpace > 0))
					break;
			}

			if (j == _text.size()) // everything in 1 line.
				lastSpace = _text.size();

			curLineWidth = 0;
			curLineHeight = 0;
			for (j = i; j < lastSpace; ++j) {
				_lines[curLine].text += _text[j];

				const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]);
				curLineWidth += curCharRect.width();
				curLineWidth += fontPtr->getGapWidth();
				if ((uint)curCharRect.height() > curLineHeight)
					curLineHeight = curCharRect.height();
			}

			_lines[curLine].bbox.right = curLineWidth;
			_lines[curLine].bbox.bottom = curLineHeight;
			if ((uint)_width < curLineWidth)
				_width = curLineWidth;

			if (lastSpace < _text.size()) {
				++curLine;
				assert(curLine == _lines.size());
				_lines.resize(curLine + 1);
				_lines[curLine].text = "";
			}

			i = lastSpace;
		}

		// Bounding box of each line relative to the first set (center aligned).
		_height = 0;
		Common::Array<Line>::iterator iter = _lines.begin();
		for (; iter != _lines.end(); ++iter) {
			Common::Rect &bbox = (*iter).bbox;
			bbox.left = (_width - bbox.right) / 2;
			bbox.right = bbox.left + bbox.right;
			bbox.top = (iter - _lines.begin()) * fontPtr->getLineHeight();
			bbox.bottom = bbox.top + bbox.bottom;
			_height += bbox.height();
		}
	} else {
		// No auto format, so all the text is copied to a single line.
		_lines[0].text = _text;
		_lines[0].bbox = Common::Rect(0, 0, _width, _height);
	}

	fontPtr->release();
}