diff options
author | ExMix <rahuba.youri@mapswithme.com> | 2014-03-13 10:47:12 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:12:41 +0300 |
commit | b04784b71678a4c96a51e23f875c3ef5ef69bf2b (patch) | |
tree | 0923b29073325dc81a78b31af53c1fd55955ba7b /map/ruler.cpp | |
parent | 69f6e406743e9bfa4813989cec71d9465b1524e2 (diff) |
prev frame animation for ruler
Diffstat (limited to 'map/ruler.cpp')
-rw-r--r-- | map/ruler.cpp | 761 |
1 files changed, 453 insertions, 308 deletions
diff --git a/map/ruler.cpp b/map/ruler.cpp index d46c4a59bc..048659c440 100644 --- a/map/ruler.cpp +++ b/map/ruler.cpp @@ -26,6 +26,15 @@ namespace { + static const int32_t MinPixelWidth = 60; + static const int32_t MinMetersWidth = 10; + static const int32_t MaxMetersWidth = 1000000; + static const int32_t CacheLength = 500; + + static const int32_t MinUnitValue = -1; + static const int32_t MaxUnitValue = numeric_limits<int32_t>::max() - 1; + static const int32_t InvalidUnitValue = MaxUnitValue + 1; + struct UnitValue { char const * m_s; @@ -33,6 +42,9 @@ namespace }; UnitValue g_arrFeets[] = { + { "10 ft", 10 }, + { "20 ft", 20 }, + { "50 ft", 50 }, { "100 ft", 100 }, { "200 ft", 200 }, { "0.1 mi", 528 }, @@ -67,6 +79,10 @@ namespace }; UnitValue g_arrMetres[] = { + { "1 m", 1 }, + { "2 m", 2 }, + { "5 m", 5 }, + { "10 m", 10 }, { "20 m", 20 }, { "50 m", 50 }, { "100 m", 100 }, @@ -90,90 +106,425 @@ namespace } } -void Ruler::AlfaAnimEnded(bool isVisible) +// ========================================================= // +Ruler::RulerFrame::RulerFrame(Framework & f, const Ruler::RulerFrame::frame_end_fn & fn, double depth) + : m_f(f) + , m_scale(0.0) + , m_depth(depth) + , m_callback(fn) { - setIsVisible(isVisible); - m_rulerAnim.reset(); } -bool Ruler::IsHidingAnim() const + +Ruler::RulerFrame::RulerFrame(const Ruler::RulerFrame & other, const Ruler::RulerFrame::frame_end_fn & fn) + : m_f(other.m_f) { - ASSERT(m_rulerAnim != NULL, ()); - AlfaCompassAnim * a = static_cast<AlfaCompassAnim *>(m_rulerAnim.get()); - return a->IsHiding(); + m_dl = other.m_dl; + m_textDL = other.m_textDL; + m_scale = other.m_scale; + m_depth = other.m_depth; + m_orgPt = other.m_orgPt; + m_callback = fn; + HideAnimate(false); } -float Ruler::GetCurrentAlfa() const +Ruler::RulerFrame::~RulerFrame() { - if (m_rulerAnim) + if (m_frameAnim) { - AlfaCompassAnim * a = static_cast<AlfaCompassAnim *>(m_rulerAnim.get()); - return a->GetCurrentAlfa(); + m_frameAnim->Cancel(); + m_frameAnim.reset(); + } + + Purge(); +} + +bool Ruler::RulerFrame::IsValid() const +{ + return m_dl != NULL && m_textDL != NULL; +} + +void Ruler::RulerFrame::Cache(const string & text, graphics::FontDesc const & f) +{ + gui::Controller * controller = m_f.GetGuiController(); + graphics::Screen * cs = controller->GetCacheScreen(); + double k = m_f.GetVisualScale(); + { + m_dl.reset(); + m_dl.reset(cs->createDisplayList()); + + cs->beginFrame(); + + cs->setDisplayList(m_dl.get()); + + cs->applyVarAlfaStates(); + + double halfLength = CacheLength / 2.0; + + graphics::GlyphKey key(strings::LastUniChar("0"), f.m_size, f.m_isMasked, f.m_color); + graphics::Glyph::Info glyphInfo(key, controller->GetGlyphCache()); + uint32_t zeroMarkGlyph = cs->mapInfo(glyphInfo); + graphics::Resource const * glyphRes = cs->fromID(zeroMarkGlyph); + + m2::RectI glyphRect(glyphRes->m_texRect); + double glyphHalfW = glyphRect.SizeX() / 2.0; + double glyphHalfH = glyphRect.SizeY() / 2.0; + double zeroMarkOffset = (glyphHalfH + 2) + 5 * k; + + graphics::Brush::Info brushInfo(graphics::Color(3, 3, 3, 255)); + uint32_t brushId = cs->mapInfo(brushInfo); + graphics::Resource const * brushRes = cs->fromID(brushId); + m2::RectU brushRect = brushRes->m_texRect; + + shared_ptr<graphics::gl::BaseTexture> glyphTexture = cs->pipeline(glyphRes->m_pipelineID).texture(); + m2::PointF brushCenter = cs->pipeline(brushRes->m_pipelineID).texture()->mapPixel(brushRect.Center()); + + // 0 1 10 11 18 17 + // -- -- -- + // || || || + // || 3, 6 9||8, 12 16||14 + // 2|--------- -------------| + // | | + // | | + // 4-------------------------- + // 5 7, 13 15 + + m2::PointD coords[] = + { + // Zero mark geometry + /*-4*/ m2::PointD(0.0, -zeroMarkOffset), + /*-3*/ m2::PointD(0.0, -zeroMarkOffset), + /*-2*/ m2::PointD(0.0, -zeroMarkOffset), + /*-1*/ m2::PointD(0.0, -zeroMarkOffset), + // Ruler geometry + /* 0*/ m2::PointD(0.0, -5.0 * k), + /* 1*/ m2::PointD(0.0, -5.0 * k), + /* 2*/ m2::PointD(0.0, -3.0 * k), + /* 3*/ m2::PointD(0.0, -3.0 * k), + /* 4*/ m2::PointD(0.0, 0.0), + /* 5*/ m2::PointD(0.0, 0.0), + /* 6*/ m2::PointD(0.0, -3.0 * k), + /* 7*/ m2::PointD(halfLength - 0.5, 0.0), + /* 8*/ m2::PointD(halfLength - 0.5, -3.0 * k), + /* 9*/ m2::PointD(halfLength - 0.5, -3.0 * k), + /*10*/ m2::PointD(halfLength - 0.5, -7.0 * k), + /*11*/ m2::PointD(halfLength - 0.5, -7.0 * k), + /*12*/ m2::PointD(halfLength - 0.5, -3.0 * k), + /*13*/ m2::PointD(halfLength - 0.5, 0.0 * k), + /*14*/ m2::PointD(CacheLength, -3.0 * k), + /*15*/ m2::PointD(CacheLength, 0.0 * k), + /*16*/ m2::PointD(CacheLength, -3.0 * k), + /*17*/ m2::PointD(CacheLength, -5.0 * k), + /*18*/ m2::PointD(CacheLength, -5.0 * k) + }; + + m2::PointF normals[] = + { + // Zero mark normals + /*-4*/ m2::PointF(-glyphHalfW + 1, -glyphHalfH), + /*-3*/ m2::PointF(-glyphHalfW + 1, glyphHalfH), + /*-2*/ m2::PointF( glyphHalfW + 1, -glyphHalfH), + /*-1*/ m2::PointF( glyphHalfW + 1, glyphHalfH), + // Ruler normals + /* 0*/ m2::PointF( 0.0 , 0.0), + /* 1*/ m2::PointF( 1.0 * k , 0.0), + /* 2*/ m2::PointF( 0.0 , 0.0), + /* 3*/ m2::PointF( 1.0 * k , 0.0), + /* 4*/ m2::PointF( 0.0 , 0.0), + /* 5*/ m2::PointF( 1.0 * k , 0.0), + /* 6*/ m2::PointF( 1.0 * k , 0.0), + /* 7*/ m2::PointF( 1.0 * k , 0.0), + /* 8*/ m2::PointF( 1.0 * k , 0.0), + /* 9*/ m2::PointF( 0.0 , 0.0), + /*10*/ m2::PointF( 0.0 , 0.0), + /*11*/ m2::PointF( 1.0 * k , 0.0), + /*12*/ m2::PointF( 1.0 * k , 0.0), + /*13*/ m2::PointF( 1.0 * k , 0.0), + /*14*/ m2::PointF( 0.0 , 0.0), + /*15*/ m2::PointF( 0.0 , 0.0), + /*16*/ m2::PointF(-1.0 * k , 0.0), + /*17*/ m2::PointF( 0.0 , 0.0), + /*18*/ m2::PointF(-1.0 * k , 0.0) + }; + + vector<m2::PointF> texCoords(ARRAY_SIZE(normals), brushCenter); + texCoords[0] = glyphTexture->mapPixel(m2::PointF(glyphRect.minX(), glyphRect.minY())); + texCoords[1] = glyphTexture->mapPixel(m2::PointF(glyphRect.minX(), glyphRect.maxY())); + texCoords[2] = glyphTexture->mapPixel(m2::PointF(glyphRect.maxX(), glyphRect.minY())); + texCoords[3] = glyphTexture->mapPixel(m2::PointF(glyphRect.maxX(), glyphRect.maxY())); + + ASSERT(ARRAY_SIZE(coords) == ARRAY_SIZE(normals), ()); + + cs->addTexturedStripStrided(coords, sizeof(m2::PointD), + normals, sizeof(m2::PointF), + &texCoords[0], sizeof(m2::PointF), 4, + m_depth, glyphRes->m_pipelineID); + + cs->addTexturedStripStrided(coords + 4, sizeof(m2::PointD), + normals + 4, sizeof(m2::PointF), + &texCoords[4], sizeof(m2::PointF), ARRAY_SIZE(coords) - 4, + m_depth, brushRes->m_pipelineID); + + cs->setDisplayList(0); + + cs->applyStates(); + + cs->endFrame(); + } + + // ============================================================ // + + ASSERT(!text.empty(), ()); + + { + m_textDL.reset(); + m_textDL.reset(cs->createDisplayList()); + + cs->beginFrame(); + cs->setDisplayList(m_textDL.get()); + cs->applyVarAlfaStates(); + + strings::UniString uniString = strings::MakeUniString(text); + size_t length = uniString.size(); + buffer_vector<graphics::Glyph::Info, 8> infos(length, graphics::Glyph::Info()); + buffer_vector<graphics::Resource::Info const *, 8> resInfos(length, NULL); + buffer_vector<uint32_t, 8> ids(length, 0); + buffer_vector<graphics::Resource const *, 8> glyphRes(length, NULL); + + for (size_t i = 0; i < uniString.size(); ++i) + { + infos[i] = graphics::Glyph::Info(graphics::GlyphKey(uniString[i], f.m_size, false, f.m_color), + controller->GetGlyphCache()); + + resInfos[i] = &infos[i]; + } + + if (cs->mapInfo(resInfos.data(), ids.data(), infos.size())) + { + uint32_t width = 0; + for (size_t i = 0; i < ids.size(); ++i) + { + graphics::Resource const * res = cs->fromID(ids[i]); + width += res->m_texRect.SizeX(); + glyphRes[i] = res; + } + + int32_t pipelineID = glyphRes[0]->m_pipelineID; + shared_ptr<graphics::gl::BaseTexture> texture = cs->pipeline(pipelineID).texture(); + double halfWidth = width / 2.0; + double lengthFromStart = 0.0; + + buffer_vector<m2::PointF, 48> coords; + buffer_vector<m2::PointF, 48> normals; + buffer_vector<m2::PointF, 48> texCoords; + + for (size_t i = 0; i < uniString.size(); ++i) + { + double baseX = lengthFromStart - halfWidth; + coords.push_back(m2::PointD(baseX, 0.0)); + coords.push_back(m2::PointD(baseX, 0.0)); + coords.push_back(m2::PointD(baseX, 0.0)); + + coords.push_back(m2::PointD(baseX, 0.0)); + coords.push_back(m2::PointD(baseX, 0.0)); + coords.push_back(m2::PointD(baseX, 0.0)); + + m2::RectI resourceRect(glyphRes[i]->m_texRect); + double w = resourceRect.SizeX(); + double h = resourceRect.SizeY(); + lengthFromStart += w; + + normals.push_back(m2::PointF(0.0, 0.0)); + normals.push_back(m2::PointF(0.0, -h)); + normals.push_back(m2::PointF(w , 0.0)); + + normals.push_back(m2::PointF(w , 0.0)); + normals.push_back(m2::PointF(0.0, -h)); + normals.push_back(m2::PointF(w , -h)); + + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.maxY()))); + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.minY()))); + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.maxY()))); + + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.maxY()))); + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.minY()))); + texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.minY()))); + } + + cs->addTexturedListStrided(coords.data(), sizeof(m2::PointF), + normals.data(), sizeof(m2::PointF), + texCoords.data(), sizeof(m2::PointF), + coords.size(), m_depth, pipelineID); + } + + cs->setDisplayList(0); + cs->endFrame(); } +} + +void Ruler::RulerFrame::Purge() +{ + m_dl.reset(); + m_textDL.reset(); +} + +bool Ruler::RulerFrame::IsHidingAnim() const +{ + ASSERT(m_frameAnim != NULL, ()); + AlfaAnimationTask * a = static_cast<AlfaAnimationTask *>(m_frameAnim.get()); + return a->IsHiding(); +} + +bool Ruler::RulerFrame::IsAnimActive() const +{ + return m_frameAnim != NULL; +} + +void Ruler::RulerFrame::SetScale(double scale) +{ + m_scale = scale; +} + +double Ruler::RulerFrame::GetScale() const +{ + return m_scale; +} + +void Ruler::RulerFrame::SetOrgPoint(const m2::PointD & org) +{ + m_orgPt = org; +} + +const m2::PointD &Ruler::RulerFrame::GetOrgPoint() const +{ + return m_orgPt; +} + +void Ruler::RulerFrame::ShowAnimate(bool needPause) +{ + double offset = (needPause == true) ? 0.07 : 0.0; + CreateAnim(IsAnimActive() ? GetCurrentAlfa() : 0.1, 1.0, 0.2, offset, true); +} - return isVisible() ? 1.0 : 0.0; +void Ruler::RulerFrame::HideAnimate(bool needPause) +{ + double offset = (needPause == true) ? 1.0 : 0.0; + double timeInterval = (needPause == true) ? 0.3 : 0.15; + CreateAnim(1.0, 0.0, timeInterval, offset, false); } -void Ruler::CreateAnim(double startAlfa, double endAlfa, double timeInterval, double timeOffset, bool isVisibleAtEnd) +void Ruler::RulerFrame::Draw(graphics::OverlayRenderer * r, const math::Matrix<double, 3, 3> & m) { - if (m_framework->GetAnimController() == NULL) + LOG(LINFO, ("Main dl = ", m_dl.get())); + ASSERT(m_dl != NULL, ()); + ASSERT(m_textDL != NULL, ()); + graphics::UniformsHolder holder; + float a = GetCurrentAlfa(); + holder.insertValue(graphics::ETransparency, a); + + r->drawDisplayList(m_dl.get(), math::Shift( + math::Scale(m, m2::PointD(m_scale, 1.0)), + m_orgPt), &holder); + + double yOffset = -(2 + 5 * m_f.GetVisualScale()); + r->drawDisplayList(m_textDL.get(), + math::Shift(m, m_orgPt + m2::PointF(CacheLength * m_scale, yOffset)), + &holder); +} + +void Ruler::RulerFrame::CreateAnim(double startAlfa, double endAlfa, double timeInterval, double timeOffset, bool isVisibleAtEnd) +{ + anim::Controller * animController = m_f.GetAnimController(); + if (animController == NULL) return; - if (m_rulerAnim) - m_rulerAnim->Cancel(); - m_rulerAnim.reset(new AlfaCompassAnim(startAlfa, endAlfa, timeInterval, timeOffset, m_framework)); - m_rulerAnim->AddCallback(anim::Task::EEnded, bind(&Ruler::AlfaAnimEnded, this, isVisibleAtEnd)); - m_framework->GetAnimController()->AddTask(m_rulerAnim); + if (m_frameAnim) + m_frameAnim->Cancel(); + + m_frameAnim.reset(new AlfaAnimationTask(startAlfa, endAlfa, timeInterval, timeOffset, &m_f)); + m_frameAnim->AddCallback(anim::Task::EEnded, bind(&RulerFrame::AnimEnded, this, isVisibleAtEnd)); + animController->AddTask(m_frameAnim); +} + +float Ruler::RulerFrame::GetCurrentAlfa() +{ + if (m_frameAnim) + { + AlfaAnimationTask * a = static_cast<AlfaAnimationTask *>(m_frameAnim.get()); + return a->GetCurrentAlfa(); + } + + return 1.0; +} + +void Ruler::RulerFrame::AnimEnded(bool isVisible) +{ + if (m_frameAnim != NULL) + { + m_frameAnim.reset(); + m_callback(isVisible, this); + } } +// ========================================================= // -void Ruler::CalcMetresDiff(double v) +double Ruler::CalcMetresDiff(double value) { - UnitValue * arrU; - int count; + UnitValue * arrU = g_arrMetres; + int count = ARRAY_SIZE(g_arrMetres); + + typedef double (*ConversionFn)(double); + ConversionFn conversionFn = &identity; switch (m_currSystem) { default: ASSERT_EQUAL ( m_currSystem, 0, () ); - arrU = g_arrMetres; - count = ARRAY_SIZE(g_arrMetres); break; case 1: arrU = g_arrFeets; count = ARRAY_SIZE(g_arrFeets); + conversionFn = &MeasurementUtils::MetersToFeet; break; case 2: arrU = g_arrYards; count = ARRAY_SIZE(g_arrYards); + conversionFn = &MeasurementUtils::MetersToYards; break; } + int prevUnitRange = m_currentRangeIndex; string s; - + double result = 0.0; + double v = conversionFn(value); if (arrU[0].m_i > v) { + m_currentRangeIndex = MinUnitValue; s = string("< ") + arrU[0].m_s; - m_metresDiff = m_minMetersWidth - 1.0; + result = MinMetersWidth - 1.0; } else if (arrU[count-1].m_i <= v) { + m_currentRangeIndex = MaxUnitValue; s = string("> ") + arrU[count-1].m_s; - m_metresDiff = m_maxMetersWidth + 1.0; + result = MaxMetersWidth + 1.0; } else for (int i = 0; i < count; ++i) { if (arrU[i].m_i > v) { - m_metresDiff = arrU[i].m_i / m_conversionFn(1.0); + m_currentRangeIndex = i; + result = arrU[i].m_i / conversionFn(1.0); s = arrU[i].m_s; break; } } - UpdateText(s); + if (m_currentRangeIndex != prevUnitRange) + UpdateText(s); + return result; } Ruler::Params::Params() @@ -182,35 +533,33 @@ Ruler::Params::Params() Ruler::Ruler(Params const & p) : base_t(p), - m_cacheLength(500), m_boundRects(1), + m_currentRangeIndex(InvalidUnitValue), m_currSystem(0), + m_mainFrame(NULL), + m_animFrames(NULL), m_framework(p.m_framework) { - gui::CachedTextView::Params pp; - - pp.m_depth = depth(); - - m_dl = NULL; - memset(m_textDL, 0, ARRAY_SIZE(m_textDL) * sizeof(void *)); + setIsVisible(false); } void Ruler::AnimateShow() { - if (!isVisible() && (m_rulerAnim == NULL || IsHidingAnim())) + RulerFrame * frame = GetMainFrame(); + if (!isVisible() && (!frame->IsAnimActive() || frame->IsHidingAnim())) { setIsVisible(true); - CreateAnim(0.1, 1.0, 0.2, 0.0, true); + frame->ShowAnimate(false); } - - if (isVisible() && (m_rulerAnim == NULL || IsHidingAnim())) - CreateAnim(GetCurrentAlfa(), 1.0, 0.2, 0.0, true); + else if (isVisible() && (frame->IsAnimActive() && frame->IsHidingAnim())) + frame->ShowAnimate(false); } void Ruler::AnimateHide() { - if (isVisible() && (m_rulerAnim == NULL || !IsHidingAnim())) - CreateAnim(1.0, 0.0, 0.3, 1.0, false); + RulerFrame * frame = GetMainFrame(); + if (isVisible() && (!frame->IsAnimActive() || !frame->IsHidingAnim())) + frame->HideAnimate(true); } void Ruler::layout() @@ -218,282 +567,81 @@ void Ruler::layout() Settings::Units units = Settings::Metric; Settings::Get("Units", units); + int prevCurrSystem = m_currSystem; switch (units) { default: ASSERT_EQUAL ( units, Settings::Metric, () ); m_currSystem = 0; - m_conversionFn = &identity; break; - case Settings::Foot: m_currSystem = 1; - m_conversionFn = &MeasurementUtils::MetersToFeet; break; - case Settings::Yard: m_currSystem = 2; - m_conversionFn = &MeasurementUtils::MetersToYards; break; } + if (prevCurrSystem != m_currSystem) + m_currentRangeIndex = InvalidUnitValue; + update(); } -void Ruler::setMinPxWidth(unsigned minPxWidth) +void Ruler::UpdateText(const string & text) { - m_minPxWidth = minPxWidth; - setIsDirtyLayout(true); -} + RulerFrame * frame = GetMainFrame(); + if (frame->IsValid()) + { + //RulerFrame * addFrame = new RulerFrame(*frame, bind(&Ruler::AnimFrameAnimEnded, this, _1, _2)); + //m_animFrames.push_back(addFrame); + delete m_animFrames; + m_animFrames = new RulerFrame(*frame, bind(&Ruler::AnimFrameAnimEnded, this, _1, _2)); + } -void Ruler::setMinMetersWidth(double v) -{ - m_minMetersWidth = v; - setIsDirtyLayout(true); + frame->Cache(text, font(EActive)); + if (isVisible()) + frame->ShowAnimate(true); } -void Ruler::setMaxMetersWidth(double v) +void Ruler::MainFrameAnimEnded(bool isVisible, RulerFrame * frame) { - m_maxMetersWidth = v; - setIsDirtyLayout(true); + setIsVisible(isVisible); + ASSERT(GetMainFrame() == frame, ()); } -void Ruler::PurgeMainDL() +void Ruler::AnimFrameAnimEnded(bool /*isVisible*/, RulerFrame * frame) { - delete m_dl; - m_dl = NULL; + //m_animFrames.remove(frame); + //delete frame; + delete frame; + m_animFrames = NULL; } -void Ruler::CacheMainDL() +Ruler::RulerFrame * Ruler::GetMainFrame() { - graphics::Screen * cs = m_controller->GetCacheScreen(); - - PurgeMainDL(); - m_dl = cs->createDisplayList(); - - cs->beginFrame(); - - cs->setDisplayList(m_dl); - - cs->applyVarAlfaStates(); - - double k = visualScale(); - double halfLength = m_cacheLength / 2.0; - - graphics::FontDesc const & f = font(EActive); - graphics::GlyphKey key(strings::LastUniChar("0"), f.m_size, f.m_isMasked, f.m_color); - graphics::Glyph::Info glyphInfo(key, m_controller->GetGlyphCache()); - uint32_t zeroMarkGlyph = cs->mapInfo(glyphInfo); - graphics::Resource const * glyphRes = cs->fromID(zeroMarkGlyph); - - m2::RectI glyphRect(glyphRes->m_texRect); - double glyphHalfW = glyphRect.SizeX() / 2.0; - double glyphHalfH = glyphRect.SizeY() / 2.0; - double zeroMarkOffset = (glyphHalfH + 2) + 5 * k; - - graphics::Brush::Info brushInfo(graphics::Color(3, 3, 3, 255)); - uint32_t brushId = cs->mapInfo(brushInfo); - graphics::Resource const * brushRes = cs->fromID(brushId); - m2::RectU brushRect = brushRes->m_texRect; - - shared_ptr<graphics::gl::BaseTexture> glyphTexture = cs->pipeline(glyphRes->m_pipelineID).texture(); - m2::PointF brushCenter = cs->pipeline(brushRes->m_pipelineID).texture()->mapPixel(brushRect.Center()); - - // 0 1 10 11 18 17 - // -- -- -- - // || || || - // || 3, 6 9||8, 12 16||14 - // 2|--------- -------------| - // | | - // | | - // 4-------------------------- - // 5 7, 13 15 - - m2::PointD coords[] = - { - // Zero mark geometry - /*-4*/ m2::PointD(0.0, -zeroMarkOffset), - /*-3*/ m2::PointD(0.0, -zeroMarkOffset), - /*-2*/ m2::PointD(0.0, -zeroMarkOffset), - /*-1*/ m2::PointD(0.0, -zeroMarkOffset), - // Ruler geometry - /* 0*/ m2::PointD(0.0, -5.0 * k), - /* 1*/ m2::PointD(0.0, -5.0 * k), - /* 2*/ m2::PointD(0.0, -3.0 * k), - /* 3*/ m2::PointD(0.0, -3.0 * k), - /* 4*/ m2::PointD(0.0, 0.0), - /* 5*/ m2::PointD(0.0, 0.0), - /* 6*/ m2::PointD(0.0, -3.0 * k), - /* 7*/ m2::PointD(halfLength - 0.5, 0.0), - /* 8*/ m2::PointD(halfLength - 0.5, -3.0 * k), - /* 9*/ m2::PointD(halfLength - 0.5, -3.0 * k), - /*10*/ m2::PointD(halfLength - 0.5, -7.0 * k), - /*11*/ m2::PointD(halfLength - 0.5, -7.0 * k), - /*12*/ m2::PointD(halfLength - 0.5, -3.0 * k), - /*13*/ m2::PointD(halfLength - 0.5, 0.0 * k), - /*14*/ m2::PointD(m_cacheLength, -3.0 * k), - /*15*/ m2::PointD(m_cacheLength, 0.0 * k), - /*16*/ m2::PointD(m_cacheLength, -3.0 * k), - /*17*/ m2::PointD(m_cacheLength, -5.0 * k), - /*18*/ m2::PointD(m_cacheLength, -5.0 * k) - }; - - m2::PointF normals[] = - { - // Zero mark normals - /*-4*/ m2::PointF(-glyphHalfW + 1, -glyphHalfH), - /*-3*/ m2::PointF(-glyphHalfW + 1, glyphHalfH), - /*-2*/ m2::PointF( glyphHalfW + 1, -glyphHalfH), - /*-1*/ m2::PointF( glyphHalfW + 1, glyphHalfH), - // Ruler normals - /* 0*/ m2::PointF( 0.0 , 0.0), - /* 1*/ m2::PointF( 1.0 * k , 0.0), - /* 2*/ m2::PointF( 0.0 , 0.0), - /* 3*/ m2::PointF( 1.0 * k , 0.0), - /* 4*/ m2::PointF( 0.0 , 0.0), - /* 5*/ m2::PointF( 1.0 * k , 0.0), - /* 6*/ m2::PointF( 1.0 * k , 0.0), - /* 7*/ m2::PointF( 1.0 * k , 0.0), - /* 8*/ m2::PointF( 1.0 * k , 0.0), - /* 9*/ m2::PointF( 0.0 , 0.0), - /*10*/ m2::PointF( 0.0 , 0.0), - /*11*/ m2::PointF( 1.0 * k , 0.0), - /*12*/ m2::PointF( 1.0 * k , 0.0), - /*13*/ m2::PointF( 1.0 * k , 0.0), - /*14*/ m2::PointF( 0.0 , 0.0), - /*15*/ m2::PointF( 0.0 , 0.0), - /*16*/ m2::PointF(-1.0 * k , 0.0), - /*17*/ m2::PointF( 0.0 , 0.0), - /*18*/ m2::PointF(-1.0 * k , 0.0) - }; - - vector<m2::PointF> texCoords(ARRAY_SIZE(normals), brushCenter); - texCoords[0] = glyphTexture->mapPixel(m2::PointF(glyphRect.minX(), glyphRect.minY())); - texCoords[1] = glyphTexture->mapPixel(m2::PointF(glyphRect.minX(), glyphRect.maxY())); - texCoords[2] = glyphTexture->mapPixel(m2::PointF(glyphRect.maxX(), glyphRect.minY())); - texCoords[3] = glyphTexture->mapPixel(m2::PointF(glyphRect.maxX(), glyphRect.maxY())); - - ASSERT(ARRAY_SIZE(coords) == ARRAY_SIZE(normals), ()); - - cs->addTexturedStripStrided(coords, sizeof(m2::PointD), - normals, sizeof(m2::PointF), - &texCoords[0], sizeof(m2::PointF), 4, - depth(), glyphRes->m_pipelineID); - - cs->addTexturedStripStrided(coords + 4, sizeof(m2::PointD), - normals + 4, sizeof(m2::PointF), - &texCoords[4], sizeof(m2::PointF), ARRAY_SIZE(coords) - 4, - depth(), brushRes->m_pipelineID); - - cs->setDisplayList(0); - - cs->applyStates(); + if (m_mainFrame == NULL) + m_mainFrame = new RulerFrame(*m_framework, bind(&Ruler::MainFrameAnimEnded, this, _1, _2), depth()); - cs->endFrame(); + return m_mainFrame; } -void Ruler::PurgeTextDL(int index) +Ruler::RulerFrame * Ruler::GetMainFrame() const { - delete m_textDL[index]; - m_textDL[index] = NULL; -} - -void Ruler::UpdateText(const string & text) -{ - ASSERT(!text.empty(), ()); - ASSERT(m_textDL[1] == NULL, ()); - swap(m_textDL[0], m_textDL[1]); - PurgeTextDL(1); - - graphics::Screen * cs = m_controller->GetCacheScreen(); - m_textDL[0] = cs->createDisplayList(); - - cs->beginFrame(); - cs->setDisplayList(m_textDL[0]); - cs->applyVarAlfaStates(); - - strings::UniString uniString = strings::MakeUniString(text); - size_t length = uniString.size(); - buffer_vector<graphics::Glyph::Info, 8> infos(length, graphics::Glyph::Info()); - buffer_vector<graphics::Resource::Info const *, 8> resInfos(length, NULL); - buffer_vector<uint32_t, 8> ids(length, 0); - buffer_vector<graphics::Resource const *, 8> glyphRes(length, NULL); - - graphics::FontDesc const & f = font(EActive); - - for (size_t i = 0; i < uniString.size(); ++i) - { - infos[i] = graphics::Glyph::Info(graphics::GlyphKey(uniString[i], f.m_size, false, f.m_color), - m_controller->GetGlyphCache()); - - resInfos[i] = &infos[i]; - } - - if (cs->mapInfo(resInfos.data(), ids.data(), infos.size())) - { - uint32_t width = 0; - for (size_t i = 0; i < ids.size(); ++i) - { - graphics::Resource const * res = cs->fromID(ids[i]); - width += res->m_texRect.SizeX(); - glyphRes[i] = res; - } - - int32_t pipelineID = glyphRes[0]->m_pipelineID; - shared_ptr<graphics::gl::BaseTexture> texture = cs->pipeline(pipelineID).texture(); - double halfWidth = width / 2.0; - double lengthFromStart = 0.0; - - buffer_vector<m2::PointF, 48> coords; - buffer_vector<m2::PointF, 48> normals; - buffer_vector<m2::PointF, 48> texCoords; - - for (size_t i = 0; i < uniString.size(); ++i) - { - double baseX = lengthFromStart - halfWidth; - coords.push_back(m2::PointD(baseX, 0.0)); - coords.push_back(m2::PointD(baseX, 0.0)); - coords.push_back(m2::PointD(baseX, 0.0)); - - coords.push_back(m2::PointD(baseX, 0.0)); - coords.push_back(m2::PointD(baseX, 0.0)); - coords.push_back(m2::PointD(baseX, 0.0)); - - m2::RectI resourceRect(glyphRes[i]->m_texRect); - double w = resourceRect.SizeX(); - double h = resourceRect.SizeY(); - lengthFromStart += w; - - normals.push_back(m2::PointF(0.0, 0.0)); - normals.push_back(m2::PointF(0.0, -h)); - normals.push_back(m2::PointF(w , 0.0)); - - normals.push_back(m2::PointF(w , 0.0)); - normals.push_back(m2::PointF(0.0, -h)); - normals.push_back(m2::PointF(w , -h)); - - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.maxY()))); - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.minY()))); - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.maxY()))); - - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.maxY()))); - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.minX(), resourceRect.minY()))); - texCoords.push_back(texture->mapPixel(m2::PointF(resourceRect.maxX(), resourceRect.minY()))); - } - - cs->addTexturedListStrided(coords.data(), sizeof(m2::PointF), - normals.data(), sizeof(m2::PointF), - texCoords.data(), sizeof(m2::PointF), - coords.size(), depth(), pipelineID); - } - - cs->setDisplayList(0); - cs->endFrame(); + ASSERT(m_mainFrame != NULL, ()); + return m_mainFrame; } void Ruler::purge() { - PurgeMainDL(); + m_currentRangeIndex = InvalidUnitValue; + delete m_mainFrame; + m_mainFrame = NULL; + + //GetRangeDeletor(m_animFrames, DeleteFunctor())(); + delete m_animFrames; + m_animFrames = NULL; + setIsVisible(false); } void Ruler::update() @@ -503,7 +651,7 @@ void Ruler::update() ScreenBase const & screen = m_framework->GetNavigator().Screen(); int const rulerHeight = my::rounds(5 * k); - int const minPxWidth = my::rounds(m_minPxWidth * k); + int const minPxWidth = my::rounds(MinPixelWidth * k); // pivot() here is the down right point of the ruler. // Get global points of ruler and distance according to minPxWidth. @@ -516,10 +664,10 @@ void Ruler::update() MercatorBounds::YToLat(pt1.y), MercatorBounds::XToLon(pt1.x)); // convert metres to units for calculating m_metresDiff - CalcMetresDiff(m_conversionFn(distanceInMetres)); + double metersDiff = CalcMetresDiff(distanceInMetres); - bool const higherThanMax = m_metresDiff > m_maxMetersWidth; - bool const lessThanMin = m_metresDiff < m_minMetersWidth; + bool const higherThanMax = metersDiff > MaxMetersWidth; + bool const lessThanMin = metersDiff < MinMetersWidth; // Calculate width of the ruler in pixels. double scalerWidthInPx = minPxWidth; @@ -532,35 +680,37 @@ void Ruler::update() // (in global coordinates) of the ruler. double const a = ang::AngleTo(pt1, pt0); - pt0 = MercatorBounds::GetSmPoint(pt1, cos(a) * m_metresDiff, sin(a) * m_metresDiff); + pt0 = MercatorBounds::GetSmPoint(pt1, cos(a) * metersDiff, sin(a) * metersDiff); scalerWidthInPx = my::rounds(pivot().Length(screen.GtoP(pt0))); } - m_scalerOrg = pivot() + m2::PointD(-scalerWidthInPx / 2, rulerHeight / 2); + m2::PointD orgPt = pivot() + m2::PointD(-scalerWidthInPx / 2, rulerHeight / 2); if (position() & graphics::EPosLeft) - m_scalerOrg.x -= scalerWidthInPx / 2; + orgPt.x -= scalerWidthInPx / 2; if (position() & graphics::EPosRight) - m_scalerOrg.x += scalerWidthInPx / 2; + orgPt.x += scalerWidthInPx / 2; if (position() & graphics::EPosAbove) - m_scalerOrg.y -= rulerHeight / 2; + orgPt.y -= rulerHeight / 2; if (position() & graphics::EPosUnder) - m_scalerOrg.y += rulerHeight / 2; + orgPt.y += rulerHeight / 2; - m_scaleKoeff = scalerWidthInPx / m_cacheLength; + RulerFrame * frame = GetMainFrame(); + frame->SetScale(scalerWidthInPx / CacheLength); + frame->SetOrgPoint(orgPt); } vector<m2::AnyRectD> const & Ruler::boundRects() const { if (isDirtyRect()) { - // TODO graphics::FontDesc const & f = font(EActive); - m2::RectD rect(m_scalerOrg, m2::PointD(m_cacheLength * m_scaleKoeff, f.m_size * 2)); + RulerFrame * frame = GetMainFrame(); + m2::RectD rect(frame->GetOrgPoint(), m2::PointD(CacheLength * frame->GetScale(), f.m_size * 2)); m_boundRects[0] = m2::AnyRectD(rect); setIsDirtyRect(false); } @@ -570,7 +720,8 @@ vector<m2::AnyRectD> const & Ruler::boundRects() const void Ruler::cache() { - CacheMainDL(); + (void)GetMainFrame(); + update(); } void Ruler::draw(graphics::OverlayRenderer * s, math::Matrix<double, 3, 3> const & m) const @@ -579,16 +730,10 @@ void Ruler::draw(graphics::OverlayRenderer * s, math::Matrix<double, 3, 3> const { checkDirtyLayout(); - graphics::UniformsHolder holder; - holder.insertValue(graphics::ETransparency, GetCurrentAlfa()); - - s->drawDisplayList(m_dl, math::Shift( - math::Scale(m, m2::PointD(m_scaleKoeff, 1.0)), - m_scalerOrg), &holder); - - double yOffset = -(2 + 5 * m_controller->GetVisualScale()); - if (m_textDL[0]) - s->drawDisplayList(m_textDL[0], - math::Shift(m, m_scalerOrg + m2::PointF(m_cacheLength * m_scaleKoeff, yOffset))); + RulerFrame * frame = GetMainFrame(); + frame->Draw(s, m); + //for_each(m_animFrames.begin(), m_animFrames.end(), bind(&Ruler::RulerFrame::Draw, _1, s, m)); + if (m_animFrames) + m_animFrames->Draw(s, m); } } |