fixed dropped-out texts in TilingRenderPolicyXXX

This commit is contained in:
rachytski 2012-01-24 14:54:09 +04:00 committed by Alex Zolotarev
parent 16164acc38
commit 2f4015193b
6 changed files with 188 additions and 57 deletions

View file

@ -94,20 +94,28 @@ void CoverageGenerator::CoverScreen(ScreenBase const & screen, int sequenceID)
if (sequenceID < m_sequenceID)
return;
ASSERT(m_workCoverage == 0, ());
m_workCoverage = m_currentCoverage->Clone();
m_workCoverage->SetStylesCache(m_workStylesCache.get());
m_workCoverage->SetScreen(screen);
ScreenCoverage * oldCoverage = m_currentCoverage;
m_workCoverage->CacheInfoLayer();
{
threads::MutexGuard g(m_mutex);
m_currentCoverage->SetStylesCache(0);
m_currentCoverage = m_workCoverage;
/// test that m_workCoverage->InfoLayer doesn't have
/// the same elements as m_currentCoverage->InfoLayer
ASSERT(!m_workCoverage->GetInfoLayer()->checkHasEquals(m_currentCoverage->GetInfoLayer()), ());
ASSERT(m_workCoverage->GetInfoLayer()->checkCached(m_workStylesCache.get()), ());
swap(m_currentCoverage, m_workCoverage);
swap(m_currentStylesCache, m_workStylesCache);
ASSERT(m_currentCoverage->GetStylesCache() == m_currentStylesCache.get(), ());
}
delete oldCoverage;
delete m_workCoverage;
m_workCoverage = 0;
m_windowHandle->invalidate();
@ -123,21 +131,29 @@ void CoverageGenerator::AddMergeTileTask(Tiler::RectInfo const & rectInfo)
void CoverageGenerator::MergeTile(Tiler::RectInfo const & rectInfo)
{
ASSERT(m_workCoverage == 0, ());
m_workCoverage = m_currentCoverage->Clone();
m_workCoverage->SetStylesCache(m_workStylesCache.get());
m_workCoverage->Merge(rectInfo);
ScreenCoverage * oldCoverage = m_currentCoverage;
m_workCoverage->CacheInfoLayer();
{
threads::MutexGuard g(m_mutex);
m_currentCoverage->SetStylesCache(0);
m_currentCoverage = m_workCoverage;
/// test that m_workCoverage->InfoLayer doesn't have
/// the same elements as m_currentCoverage->InfoLayer
ASSERT(!m_workCoverage->GetInfoLayer()->checkHasEquals(m_currentCoverage->GetInfoLayer()), ());
ASSERT(m_workCoverage->GetInfoLayer()->checkCached(m_workStylesCache.get()), ());
swap(m_currentCoverage, m_workCoverage);
swap(m_currentStylesCache, m_workStylesCache);
ASSERT(m_currentCoverage->GetStylesCache() == m_currentStylesCache.get(), ());
}
delete oldCoverage;
/// we should delete workCoverage
delete m_workCoverage;
m_workCoverage = 0;
m_windowHandle->invalidate();

View file

@ -13,8 +13,13 @@
#include "coverage_generator.hpp"
ScreenCoverage::ScreenCoverage()
: m_tiler(0, 0), m_stylesCache(0)
{}
: m_tiler(0, 0),
m_drawScale(0),
m_stylesCache(0),
m_infoLayer(new yg::InfoLayer())
{
m_infoLayer->setCouldOverlap(false);
}
ScreenCoverage::ScreenCoverage(TileRenderer * tileRenderer,
CoverageGenerator * coverageGenerator,
@ -23,9 +28,11 @@ ScreenCoverage::ScreenCoverage(TileRenderer * tileRenderer,
: m_tileRenderer(tileRenderer),
m_tiler(tileSize, scaleEtalonSize),
m_coverageGenerator(coverageGenerator),
m_infoLayer(new yg::InfoLayer()),
m_drawScale(0),
m_stylesCache(0)
{
m_infoLayer.setCouldOverlap(false);
m_infoLayer->setCouldOverlap(false);
}
ScreenCoverage * ScreenCoverage::Clone()
@ -53,7 +60,8 @@ ScreenCoverage * ScreenCoverage::Clone()
tileCache->writeUnlock();
res->m_infoLayer = m_infoLayer;
res->m_infoLayer.reset();
res->m_infoLayer.reset(m_infoLayer->clone());
res->m_stylesCache = 0;
return res;
@ -64,6 +72,11 @@ void ScreenCoverage::SetStylesCache(yg::StylesCache * stylesCache)
m_stylesCache = stylesCache;
}
yg::StylesCache * ScreenCoverage::GetStylesCache() const
{
return m_stylesCache;
}
void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
{
if (m_tileRects.find(ri) == m_tileRects.end())
@ -98,19 +111,31 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
if (addTile)
{
m_infoLayer.merge(*tile->m_infoLayer.get(),
tile->m_tileScreen.PtoGMatrix() * m_screen.GtoPMatrix());
yg::InfoLayer * tileInfoLayerCopy = tile->m_infoLayer->clone();
if (!m_stylesCache)
LOG(LWARNING, ("no styles cache"));
else
{
m_infoLayer.cache(m_stylesCache);
m_stylesCache->upload();
}
m_infoLayer->merge(*tileInfoLayerCopy,
tile->m_tileScreen.PtoGMatrix() * m_screen.GtoPMatrix());
delete tileInfoLayerCopy;
}
}
void ScreenCoverage::CacheInfoLayer()
{
if (!m_stylesCache)
{
LOG(LWARNING, ("no styles cache"));
return;
}
m_infoLayer->cache(m_stylesCache);
/// asserting, that all visible elements is cached
ASSERT(m_infoLayer->checkCached(m_stylesCache), ());
m_stylesCache->upload();
}
void ScreenCoverage::Remove(Tile const *)
{
}
@ -144,7 +169,7 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
else
CHECK(drawScale == allRects[i].m_drawScale, (drawScale, allRects[i].m_drawScale));
m_drawScale = drawScale;
m_drawScale = drawScale == -1 ? 0 : drawScale;
for (unsigned i = 0; i < allRects.size(); ++i)
{
@ -192,16 +217,13 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
m_tiles = tiles;
m_infoLayer.clear();
for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
m_infoLayer.merge(*((*it)->m_infoLayer.get()), (*it)->m_tileScreen.PtoGMatrix() * screen.GtoPMatrix());
m_infoLayer->clear();
if (!m_stylesCache)
LOG(LWARNING, ("no styles cache"));
else
for (TileSet::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
{
m_infoLayer.cache(m_stylesCache);
m_stylesCache->upload();
yg::InfoLayer * tileInfoLayerCopy = (*it)->m_infoLayer->clone();
m_infoLayer->merge(*tileInfoLayerCopy, (*it)->m_tileScreen.PtoGMatrix() * screen.GtoPMatrix());
delete tileInfoLayerCopy;
}
/// clearing all old commands
@ -256,9 +278,19 @@ void ScreenCoverage::Draw(yg::gl::Screen * s, ScreenBase const & screen)
s->blit(&infos[0], infos.size(), true);
if (m_stylesCache)
{
ASSERT(m_infoLayer->checkCached(m_stylesCache), ());
s->setAdditionalSkinPage(m_stylesCache->cachePage());
}
else
LOG(LINFO, ("no styles cache"));
m_infoLayer.draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix());
m_infoLayer->draw(s, m_screen.PtoGMatrix() * screen.GtoPMatrix());
}
yg::InfoLayer * ScreenCoverage::GetInfoLayer() const
{
return m_infoLayer.get();
}
void ScreenCoverage::EndFrame(yg::gl::Screen *s)

View file

@ -43,7 +43,7 @@ private:
TileRectSet m_tileRects; //< rects, that forms a set of tiles in current rect.
TileSet m_tiles; //< set of tiles, that are visible for the m_screen
yg::InfoLayer m_infoLayer; //< composite infoLayers for visible tiles
scoped_ptr<yg::InfoLayer> m_infoLayer; //< composite infoLayers for visible tiles
//< scales, which are used in the tiles, drawn in the current screen.
int m_drawScale;
@ -64,7 +64,13 @@ public:
size_t scaleEtalonSize);
ScreenCoverage * Clone();
void SetStylesCache(yg::StylesCache * stylesCache);
yg::StylesCache * GetStylesCache() const;
yg::InfoLayer * GetInfoLayer() const;
void CacheInfoLayer();
/// add rendered tile to coverage. Tile is locked, so make sure to unlock it in case it's not needed.
void Merge(Tiler::RectInfo const & ri);

View file

@ -38,6 +38,26 @@ namespace yg
: m_couldOverlap(true)
{}
InfoLayer::InfoLayer(InfoLayer const & src)
{
m_couldOverlap = src.m_couldOverlap;
vector<shared_ptr<OverlayElement> > elems;
src.m_tree.ForEach(MakeBackInsertFunctor(elems));
math::Matrix<double, 3, 3> id = math::Identity<double, 3>();
for (unsigned i = 0; i < elems.size(); ++i)
{
shared_ptr<OverlayElement> e(elems[i]->clone(id));
e->setIsVisible(true);
e->setIsNeedRedraw(true);
processOverlayElement(e);
}
}
void InfoLayer::setCouldOverlap(bool flag)
{
m_couldOverlap = flag;
@ -214,22 +234,29 @@ namespace yg
sort(v.begin(), v.end(), &greater_priority);
/// making all elements visible
for (unsigned i = 0; i < v.size(); ++i)
v[i]->setIsNeedRedraw(true);
/// caching on StylesCache::m_maxPagesCount at most
/// collecting all the unpacked rects from all elements
vector<m2::PointU> sizes;
sizes.reserve(100);
/// some glyphs will be counted twice(probably a lot of them).
/// that way we'll actually waste a lot of texture space.
for (unsigned i = 0; i < v.size(); ++i)
v[i]->getNonPackedRects(stylesCache, sizes);
if (sizes.empty())
return;
/// if there are enough room to cache all the elements
if (stylesCache->hasRoom(&sizes[0], sizes.size()))
{
/// cache them
for (unsigned i = 0; i < v.size(); ++i)
v[i]->map(stylesCache);
}
@ -255,12 +282,16 @@ namespace yg
}
}
if (v.size() - pos > 1)
if (v.size() - pos >= 1)
LOG(LINFO, ("making ", v.size() - pos, "elements invisible"));
/// making all uncached elements invisible
/// partially uncached elements should be invisible
for (; pos < v.size(); ++pos)
v[pos]->setIsNeedRedraw(false);
{
sizes.clear();
v[pos]->getNonPackedRects(stylesCache, sizes);
v[pos]->setIsNeedRedraw(sizes.empty());
}
}
}
@ -307,5 +338,43 @@ namespace yg
// LOG(LINFO, ("clipped out", clippedCnt, "elements,", elemCnt, "elements total"));
}
bool InfoLayer::checkHasEquals(InfoLayer const * l) const
{
vector<shared_ptr<OverlayElement> > v0;
m_tree.ForEach(MakeBackInsertFunctor(v0));
sort(v0.begin(), v0.end());
vector<shared_ptr<OverlayElement> > v1;
l->m_tree.ForEach(MakeBackInsertFunctor(v1));
sort(v1.begin(), v1.end());
vector<shared_ptr<OverlayElement> > res;
set_intersection(v0.begin(), v0.end(), v1.begin(), v1.end(), back_inserter(res));
return !res.empty();
}
bool InfoLayer::checkCached(StylesCache * s) const
{
vector<shared_ptr<OverlayElement> > v;
m_tree.ForEach(MakeBackInsertFunctor(v));
for (unsigned i = 0; i < v.size(); ++i)
if (v[i]->isNeedRedraw())
if (!v[i]->find(s))
return false;
return true;
}
InfoLayer * InfoLayer::clone() const
{
InfoLayer * res = new InfoLayer(*this);
return res;
}
}

View file

@ -32,9 +32,12 @@ namespace yg
void addOverlayElement(shared_ptr<OverlayElement> const & oe);
void replaceOverlayElement(shared_ptr<OverlayElement> const & oe);
friend class InfoLayer;
public:
InfoLayer();
InfoLayer(InfoLayer const & src);
void draw(gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m);
@ -53,5 +56,10 @@ namespace yg
void merge(InfoLayer const & infoLayer, math::Matrix<double, 3, 3> const & m);
void clip(m2::RectI const & r);
bool checkHasEquals(InfoLayer const * l) const;
bool checkCached(StylesCache * s) const;
InfoLayer * clone() const;
};
}

View file

@ -140,18 +140,18 @@ namespace yg
{
GlyphLayoutElem const & elem = layout.entries()[i];
GlyphKey glyphKey(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
GlyphKey gk(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
bool packed = skinPage->findGlyph(glyphKey) != 0x00FFFFFF;
bool packed = skinPage->findGlyph(gk) != 0x00FFFFFF;
if (!packed)
{
if (skinPage->hasRoom(glyphKey, glyphCache))
if (skinPage->hasRoom(gk, glyphCache))
{
skinPage->mapGlyph(glyphKey, glyphCache);
skinPage->mapGlyph(gk, glyphCache);
packed = true;
}
}
@ -171,12 +171,12 @@ namespace yg
{
GlyphLayoutElem const & elem = layout.entries()[i];
GlyphKey glyphKey(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
GlyphKey gk(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
if (skinPage->findGlyph(glyphKey) == 0x00FFFFFF)
if (skinPage->findGlyph(gk) == 0x00FFFFFF)
return false;
}
@ -198,14 +198,14 @@ namespace yg
{
GlyphLayoutElem const & elem = layout.entries()[i];
GlyphKey glyphKey(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
GlyphKey gk(elem.m_sym,
desc.m_size,
desc.m_isMasked,
desc.m_isMasked ? desc.m_maskColor : desc.m_color);
if (skinPage->findGlyph(glyphKey) == 0x00FFFFFF)
if (skinPage->findGlyph(gk) == 0x00FFFFFF)
{
shared_ptr<GlyphInfo> gi = glyphCache->getGlyphInfo(glyphKey);
shared_ptr<GlyphInfo> gi = glyphCache->getGlyphInfo(gk);
v.push_back(m2::PointU(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4));
}
}