From 840ca2bb19bb287cee1558c51c6fd896e74e3595 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 10 Jan 2017 17:16:35 +0300 Subject: [PATCH 1/2] Added different frequency of arrows on traffic lines --- drape/drape_tests/CMakeLists.txt | 1 + drape/drape_tests/drape_tests.pro | 1 + drape/drape_tests/static_texture_tests.cpp | 16 +++++++ drape/shaders/traffic_vertex_shader.vsh | 11 ++--- drape/static_texture.cpp | 16 ++++--- drape/static_texture.hpp | 6 ++- drape_frontend/traffic_generator.cpp | 52 +++++++++++++++++----- drape_frontend/traffic_generator.hpp | 5 ++- drape_frontend/traffic_renderer.cpp | 2 +- 9 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 drape/drape_tests/static_texture_tests.cpp diff --git a/drape/drape_tests/CMakeLists.txt b/drape/drape_tests/CMakeLists.txt index 3d80914617..63159690d3 100644 --- a/drape/drape_tests/CMakeLists.txt +++ b/drape/drape_tests/CMakeLists.txt @@ -39,6 +39,7 @@ set( img.hpp memory_comparer.hpp pointers_tests.cpp + static_texture_tests.cpp stipple_pen_tests.cpp texture_of_colors_tests.cpp testingmain.cpp diff --git a/drape/drape_tests/drape_tests.pro b/drape/drape_tests/drape_tests.pro index c204c72dd4..1aaf5536a2 100644 --- a/drape/drape_tests/drape_tests.pro +++ b/drape/drape_tests/drape_tests.pro @@ -40,6 +40,7 @@ SOURCES += \ glyph_packer_test.cpp \ img.cpp \ pointers_tests.cpp \ + static_texture_tests.cpp \ stipple_pen_tests.cpp \ testingmain.cpp \ texture_of_colors_tests.cpp \ diff --git a/drape/drape_tests/static_texture_tests.cpp b/drape/drape_tests/static_texture_tests.cpp new file mode 100644 index 0000000000..6d8c726755 --- /dev/null +++ b/drape/drape_tests/static_texture_tests.cpp @@ -0,0 +1,16 @@ +#include "testing/testing.hpp" + +#include "drape/static_texture.hpp" + +#include +#include + +UNIT_TEST(CheckTrafficArrowTextures) +{ + static std::vector skinPaths = {"6plus", "mdpi", "hdpi", "xhdpi", "xxhdpi"}; + for (size_t i = 0; i < skinPaths.size(); ++i) + { + dp::StaticTexture texture("traffic-arrow", skinPaths[i], nullptr); + TEST(texture.IsLoadingCorrect(), ()); + } +} diff --git a/drape/shaders/traffic_vertex_shader.vsh b/drape/shaders/traffic_vertex_shader.vsh index 7625f7cc79..6aba2dbb21 100644 --- a/drape/shaders/traffic_vertex_shader.vsh +++ b/drape/shaders/traffic_vertex_shader.vsh @@ -1,6 +1,6 @@ attribute vec3 a_position; attribute vec4 a_normal; -attribute vec2 a_colorTexCoord; +attribute vec4 a_colorTexCoord; uniform mat4 modelView; uniform mat4 projection; @@ -13,7 +13,7 @@ varying vec2 v_maskTexCoord; varying float v_halfLength; const float kShapeCoordScalar = 1000.0; -const float kMinVisibleArrowPart = 0.9; +const float kArrowVSize = 0.25; void main(void) { @@ -33,9 +33,10 @@ void main(void) } float uOffset = length(vec4(kShapeCoordScalar, 0, 0, 0) * modelView) * a_normal.w; - v_colorTexCoord = a_colorTexCoord; - v_maskTexCoord = vec2(uOffset * u_trafficParams.z, 0.5 * a_normal.z + 0.5) * u_trafficParams.w; - v_maskTexCoord.x *= step(kMinVisibleArrowPart, v_maskTexCoord.x); + v_colorTexCoord = a_colorTexCoord.xy; + float v = mix(a_colorTexCoord.z, a_colorTexCoord.z + kArrowVSize, 0.5 * a_normal.z + 0.5); + v_maskTexCoord = vec2(uOffset * u_trafficParams.z, v) * u_trafficParams.w; + v_maskTexCoord.x *= step(a_colorTexCoord.w, v_maskTexCoord.x); v_halfLength = a_normal.z; vec4 pos = vec4(transformedAxisPos, a_position.z, 1.0) * projection; float w = pos.w; diff --git a/drape/static_texture.cpp b/drape/static_texture.cpp index 830f739eef..9e2e91ad90 100644 --- a/drape/static_texture.cpp +++ b/drape/static_texture.cpp @@ -20,7 +20,7 @@ namespace using TLoadingCompletion = function; using TLoadingFailure = function; -void LoadData(string const & textureName, string const & skinPathName, +bool LoadData(string const & textureName, string const & skinPathName, TLoadingCompletion const & completionHandler, TLoadingFailure const & failureHandler) { @@ -39,15 +39,17 @@ void LoadData(string const & textureName, string const & skinPathName, catch (RootException & e) { failureHandler(e.what()); - return; + return false; } int w, h, bpp; - unsigned char * data = stbi_png_load_from_memory(&rawData[0], static_cast(rawData.size()), &w, &h, &bpp, 0); + unsigned char * data = stbi_png_load_from_memory(&rawData[0], static_cast(rawData.size()), + &w, &h, &bpp, 0); ASSERT_EQUAL(bpp, 4, ("Incorrect texture format")); completionHandler(data, w, h); stbi_image_free(data); + return true; } class StaticResourceInfo : public Texture::ResourceInfo @@ -66,10 +68,10 @@ StaticTexture::StaticTexture(string const & textureName, string const & skinPath : m_textureName(textureName) , m_info(make_unique_dp()) { - Load(skinPathName, allocator); + m_isLoadingCorrect = Load(skinPathName, allocator); } -void StaticTexture::Load(string const & skinPathName, ref_ptr allocator) +bool StaticTexture::Load(string const & skinPathName, ref_ptr allocator) { auto completionHandler = [this, &allocator](unsigned char * data, uint32_t width, uint32_t height) { @@ -90,13 +92,13 @@ void StaticTexture::Load(string const & skinPathName, ref_ptr allocator) { Destroy(); - Load(skinPathName, allocator); + m_isLoadingCorrect = Load(skinPathName, allocator); } ref_ptr StaticTexture::FindResource(Texture::Key const & key, bool & newResource) diff --git a/drape/static_texture.hpp b/drape/static_texture.hpp index 9385faf917..aa2aa7e4c5 100644 --- a/drape/static_texture.hpp +++ b/drape/static_texture.hpp @@ -23,12 +23,16 @@ public: void Invalidate(string const & skinPathName, ref_ptr allocator); + bool IsLoadingCorrect() const { return m_isLoadingCorrect; } + private: void Fail(); - void Load(string const & skinPathName, ref_ptr allocator); + bool Load(string const & skinPathName, ref_ptr allocator); string m_textureName; drape_ptr m_info; + + bool m_isLoadingCorrect; }; } // namespace dp diff --git a/drape_frontend/traffic_generator.cpp b/drape_frontend/traffic_generator.cpp index 373847354b..61239beb3b 100644 --- a/drape_frontend/traffic_generator.cpp +++ b/drape_frontend/traffic_generator.cpp @@ -24,6 +24,31 @@ namespace df namespace { +// Values of the following arrays are based on traffic-arrow texture. +static array(traffic::SpeedGroup::Count)> kCoordVOffsets = +{ + 0.75f, // G0 + 0.75f, // G1 + 0.75f, // G2 + 0.5f, // G3 + 0.25f, // G4 + 0.0f, // G5 + 0.75f, // TempBlock + 0.0f, // Unknown +}; + +static array(traffic::SpeedGroup::Count)> kMinCoordU = +{ + 0.15f, // G0 + 0.15f, // G1 + 0.15f, // G2 + 0.33f, // G3 + 0.5f, // G4 + 0.0f, // G5 + 0.15f, // TempBlock + 0.0f, // Unknown +}; + dp::BindingInfo const & GetTrafficStaticBindingInfo() { static unique_ptr s_info; @@ -52,7 +77,7 @@ dp::BindingInfo const & GetTrafficLineStaticBindingInfo() } void SubmitStaticVertex(glsl::vec3 const & pivot, glsl::vec2 const & normal, float side, - float offsetFromStart, glsl::vec2 const & texCoord, + float offsetFromStart, glsl::vec4 const & texCoord, vector & staticGeom) { staticGeom.emplace_back(pivot, TrafficStaticVertex::TNormal(normal, side, offsetFromStart), texCoord); @@ -63,7 +88,7 @@ void GenerateCapTriangles(glsl::vec3 const & pivot, vector const & n vector & staticGeometry) { float const kEps = 1e-5; - glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); + glsl::vec4 const uv = glsl::vec4(glsl::ToVec2(colorRegion.GetTexRect().Center()), 0.0f, 0.0f); size_t const trianglesCount = normals.size() / 3; for (int j = 0; j < trianglesCount; j++) { @@ -141,6 +166,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg ASSERT(m_colorsCacheValid, ()); dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[static_cast(segmentColoringIt->second)]; + float const vOffset = kCoordVOffsets[static_cast(segmentColoringIt->second)]; + float const minU = kMinCoordU[static_cast(segmentColoringIt->second)]; int width = 0; if (TrafficRenderer::CanBeRendereredAsLine(g.m_roadClass, tileKey.m_zoomLevel, width)) @@ -161,7 +188,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg { vector staticGeometry; bool const generateCaps = (tileKey.m_zoomLevel > kGenerateCapsZoomLevel[static_cast(g.m_roadClass)]); - GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), generateCaps, depth, staticGeometry); + GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), generateCaps, depth, + vOffset, minU, staticGeometry); if (staticGeometry.empty()) continue; @@ -215,7 +243,8 @@ void TrafficGenerator::FlushGeometry(TrafficBatcherKey const & key, dp::GLState void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - bool generateCaps, float depth, vector & staticGeometry) + bool generateCaps, float depth, float vOffset, float minU, + vector & staticGeometry) { vector const & path = polyline.GetPoints(); ASSERT_GREATER(path.size(), 1, ()); @@ -229,7 +258,8 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c glsl::vec2 lastPoint, lastTangent, lastLeftNormal, lastRightNormal; bool firstFilled = false; - glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); + glsl::vec4 const uvStart = glsl::vec4(glsl::ToVec2(colorRegion.GetTexRect().Center()), vOffset, 1.0f); + glsl::vec4 const uvEnd = glsl::vec4(uvStart.x, uvStart.y, uvStart.z, minU); for (size_t i = 1; i < path.size(); ++i) { if (path[i].EqualDxDy(path[i - 1], 1.0E-5)) @@ -257,12 +287,12 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c glsl::vec3 const startPivot = glsl::vec3(p1, depth); glsl::vec3 const endPivot = glsl::vec3(p2, depth); - SubmitStaticVertex(startPivot, rightNormal, -1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uv, staticGeometry); - SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uv, staticGeometry); - SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(endPivot, leftNormal, 1.0f, maskSize, uv, staticGeometry); + SubmitStaticVertex(startPivot, rightNormal, -1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uvEnd, staticGeometry); + SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uvEnd, staticGeometry); + SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(endPivot, leftNormal, 1.0f, maskSize, uvEnd, staticGeometry); } // Generate caps. diff --git a/drape_frontend/traffic_generator.hpp b/drape_frontend/traffic_generator.hpp index 7983a1cddd..e9c331c8d2 100644 --- a/drape_frontend/traffic_generator.hpp +++ b/drape_frontend/traffic_generator.hpp @@ -93,7 +93,7 @@ struct TrafficStaticVertex { using TPosition = glsl::vec3; using TNormal = glsl::vec4; - using TTexCoord = glsl::vec2; + using TTexCoord = glsl::vec4; TrafficStaticVertex() = default; TrafficStaticVertex(TPosition const & position, TNormal const & normal, @@ -180,7 +180,8 @@ private: void GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - bool generateCaps, float depth, vector & staticGeometry); + bool generateCaps, float depth, float vOffset, float minU, + vector & staticGeometry); void GenerateLineSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, float depth, vector & staticGeometry); diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index c3ab0c3c08..139d8ba5d9 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -24,7 +24,7 @@ int constexpr kMinVisibleArrowZoomLevel = 16; int constexpr kRoadClass2MinVisibleArrowZoomLevel = 17; int constexpr kOutlineMinZoomLevel = 14; -float const kTrafficArrowAspect = 24.0f / 8.0f; +float const kTrafficArrowAspect = 128.0f / 8.0f; float const kLeftWidthInPixel[] = { From 19501f8f985e97972289ede921dc6beda5597235 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 10 Jan 2017 17:17:00 +0300 Subject: [PATCH 2/2] Updated traffic arrow textures --- data/resources-6plus_clear/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-6plus_dark/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-6plus_legacy/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-hdpi_clear/traffic-arrow.png | Bin 179 -> 15042 bytes data/resources-hdpi_dark/traffic-arrow.png | Bin 179 -> 15042 bytes data/resources-hdpi_legacy/traffic-arrow.png | Bin 179 -> 15042 bytes data/resources-mdpi_clear/traffic-arrow.png | Bin 179 -> 14744 bytes data/resources-mdpi_dark/traffic-arrow.png | Bin 179 -> 14744 bytes data/resources-mdpi_legacy/traffic-arrow.png | Bin 179 -> 14744 bytes data/resources-xhdpi_clear/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-xhdpi_dark/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-xhdpi_legacy/traffic-arrow.png | Bin 296 -> 15056 bytes data/resources-xxhdpi_clear/traffic-arrow.png | Bin 561 -> 15928 bytes data/resources-xxhdpi_dark/traffic-arrow.png | Bin 561 -> 15928 bytes .../resources-xxhdpi_legacy/traffic-arrow.png | Bin 561 -> 15928 bytes drape/static_texture.cpp | 5 +++++ drape/symbols_texture.cpp | 6 ++++++ 17 files changed, 11 insertions(+) diff --git a/data/resources-6plus_clear/traffic-arrow.png b/data/resources-6plus_clear/traffic-arrow.png index 64f987122c958b105a9e08047117316007ebb3f0..87b2190d58f7f2f563fd4042624cf18e414dc338 100644 GIT binary patch literal 15056 zcmeI3e{35?7RSd)O4HCDlvV|DrCm0H0>^rHZLbqAj_VMoBr0xxIW(n5$!0xHR<*s3 zcSD>g9M)Y`6;;P~1f{cu1_ zHnLy6`Z~*K(MEQw6c)m%W;m#|j-_Gu*p`Sowo~;**^Pl3e?~?D63|qbOd_5%fG$$!{D4YK^{XiV-3ZOW%Zca7|zX{KbJ9~l{Oj<}tAdH~6NK3;I~E*FP9IAb(v zDj6%|@2B5*0rAc_mVXL`fsh4pHPYN{Sbq0$)xP zRSTNba5`=eEvoV`4ihkG8b~LW)uje?Q#S_nMN$^J7fp<65)Kz~mmO~+Q8u+^+9EQmCnvL)Lasu7G*`Jf z4HZ*QM|3?N$gQ%DIfP7ev$d)ur^MV8R#Yu%k-gc^m&%GYFGhqR#e@N*uIB`i6NQNA zl_f!TH~dC$%YuLf$$6H<2E2Ig5B1MQ)xVk$o?3hs-=iK=o;PbU;J zpe2+6$fuG6e!kdfJoP?_>yLTeoX0J>yl$6IQN$d?a2S^_2p!VZVQa^r(7D4Us;ek`aag`s ztUu~;K~Ah!>p4-ZSGWc>>gD<+$*ZU?=ynT=T`iOd3$`Fpds;(hpAyG>thq%0$GMaV zvmjNgW}p>2imha{p6%1E8xGBHo$H8e_9>N8(gw8lU?V%X2@A(s;ncD;_Fk41)jHn- zsa zeR$FO&P(y`Qt7r!OY!bfX;Ime)Xab@pRJ@BQ(5P6?x5&Kj}9>4l_a<1=S!PQ6&+dz z#(P5=+R=u!GF_54FDmURtK3#pdOf%h>&OdpwZeYo?Na7i(K7^keBlevFY~Kh*bTq1 zQJm2)92gHrli)OnHpN9mgga1NI1QpraS;*W4ipzogJ@G+L`1j)#f8%#+7uTN5$-^7 z;WUUg#YIGfJ5XFW4WdnP5fR}I6cA6EMMQ)< zP+T|-qD^rT5#bIL7fyp{Q(QzuxC6z7(;(Uu7ZDNeKyl$Th&IJVM1(s~TsRG)O>q$s z;SLlRPJ?JuTtq~;1I2~YAleic5fSb{ap5$GHpN9mgga1NI1QpraS;*W4ipzogJ@G+ zL`1j)#f8%#+Ly#tQ+y*3CedqvBj|m<8;{>kr@i<|Y6tu4oH2MKb^R;-k%7Zv>aObiVzUi32?^T)l>kMNge;A3Jjw zY+Z8y_+OL5w{7pa9~}E(_)ml_!Wsz4TiD^Z{_joGE0J)0++&do+n?BBBI z%h{DP_rA7o*(dASW2>k3Tv#=AaYeA|gNng>9;j$Ik0k3r7OQX z@?@QTzjoU=`|l0eV;7#^@z$TS!I#BnK5~4q&hga6(eu@PE2mlJ){3j9x+-7(`h_KZ z%LnVOtXR@l_t3$q>ea#T?)oG#(|_v4@Of~>RZ}%cEL7Qp&3y0P_oh7h=)0?a`gBb< z_{=sBeYU$|`tUcmOjbRqobCyHSTps?kMGqs?Wp|rgHG_ymy_=u{-$=K{i{ll`t;x% z7e79G@+aTSBY&S7zq@MJ(YvcWm+d-w#FsTW9v>Gw(d}#N^ifZyz~%eRgHx2BpZ};6C`f@2`L9z{SJc!^6v-+uIV{ z8(!n!DrzfFbzGwchfc0*-{5#Z#jYD#yS9C)xLd*{qAWro9XpxkeS#B0GOSv Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 zcmV+@0oVSCP)Px#;z>k7R9FdPU>F6XAuy;y;Q#;sdw@6^h}i~}!|3H0pvP|mF$g>d;(8#KpqJf) z!XBW94+AkW_zC1J0b;X3;XqnD0_f3I$i7Eop9J!$nmriF^$^e@Y2@l9pf4IIZ%07Q z3!wZAAfCy{$OvMS4JZkK|76=rJ&nJBMy&?oNx*0hyK#QvSm41!H3MHdLc-E9}=(;=-UIxJ_fQ!Ts3$L u8UUb%Py-N;xQ5WkZVD5~A*0gN4gmnLO3NOs|7OSl0000^rHZLbqAj_VMoBr0xxIW(n5$!0xHR<*s3 zcSD>g9M)Y`6;;P~1f{cu1_ zHnLy6`Z~*K(MEQw6c)m%W;m#|j-_Gu*p`Sowo~;**^Pl3e?~?D63|qbOd_5%fG$$!{D4YK^{XiV-3ZOW%Zca7|zX{KbJ9~l{Oj<}tAdH~6NK3;I~E*FP9IAb(v zDj6%|@2B5*0rAc_mVXL`fsh4pHPYN{Sbq0$)xP zRSTNba5`=eEvoV`4ihkG8b~LW)uje?Q#S_nMN$^J7fp<65)Kz~mmO~+Q8u+^+9EQmCnvL)Lasu7G*`Jf z4HZ*QM|3?N$gQ%DIfP7ev$d)ur^MV8R#Yu%k-gc^m&%GYFGhqR#e@N*uIB`i6NQNA zl_f!TH~dC$%YuLf$$6H<2E2Ig5B1MQ)xVk$o?3hs-=iK=o;PbU;J zpe2+6$fuG6e!kdfJoP?_>yLTeoX0J>yl$6IQN$d?a2S^_2p!VZVQa^r(7D4Us;ek`aag`s ztUu~;K~Ah!>p4-ZSGWc>>gD<+$*ZU?=ynT=T`iOd3$`Fpds;(hpAyG>thq%0$GMaV zvmjNgW}p>2imha{p6%1E8xGBHo$H8e_9>N8(gw8lU?V%X2@A(s;ncD;_Fk41)jHn- zsa zeR$FO&P(y`Qt7r!OY!bfX;Ime)Xab@pRJ@BQ(5P6?x5&Kj}9>4l_a<1=S!PQ6&+dz z#(P5=+R=u!GF_54FDmURtK3#pdOf%h>&OdpwZeYo?Na7i(K7^keBlevFY~Kh*bTq1 zQJm2)92gHrli)OnHpN9mgga1NI1QpraS;*W4ipzogJ@G+L`1j)#f8%#+7uTN5$-^7 z;WUUg#YIGfJ5XFW4WdnP5fR}I6cA6EMMQ)< zP+T|-qD^rT5#bIL7fyp{Q(QzuxC6z7(;(Uu7ZDNeKyl$Th&IJVM1(s~TsRG)O>q$s z;SLlRPJ?JuTtq~;1I2~YAleic5fSb{ap5$GHpN9mgga1NI1QpraS;*W4ipzogJ@G+ zL`1j)#f8%#+Ly#tQ+y*3CedqvBj|m<8;{>kr@i<|Y6tu4oH2MKb^R;-k%7Zv>aObiVzUi32?^T)l>kMNge;A3Jjw zY+Z8y_+OL5w{7pa9~}E(_)ml_!Wsz4TiD^Z{_joGE0J)0++&do+n?BBBI z%h{DP_rA7o*(dASW2>k3Tv#=AaYeA|gNng>9;j$Ik0k3r7OQX z@?@QTzjoU=`|l0eV;7#^@z$TS!I#BnK5~4q&hga6(eu@PE2mlJ){3j9x+-7(`h_KZ z%LnVOtXR@l_t3$q>ea#T?)oG#(|_v4@Of~>RZ}%cEL7Qp&3y0P_oh7h=)0?a`gBb< z_{=sBeYU$|`tUcmOjbRqobCyHSTps?kMGqs?Wp|rgHG_ymy_=u{-$=K{i{ll`t;x% z7e79G@+aTSBY&S7zq@MJ(YvcWm+d-w#FsTW9v>Gw(d}#N^ifZyz~%eRgHx2BpZ};6C`f@2`L9z{SJc!^6v-+uIV{ z8(!n!DrzfFbzGwchfc0*-{5#Z#jYD#yS9C)xLd*{qAWro9XpxkeS#B0GOSv Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 zcmV+@0oVSCP)Px#;z>k7R9FdPU>F6XAuy;y;Q#;sdw@6^h}i~}!|3H0pvP|mF$g>d;(8#KpqJf) z!XBW94+AkW_zC1J0b;X3;XqnD0_f3I$i7Eop9J!$nmriF^$^e@Y2@l9pf4IIZ%07Q z3!wZAAfCy{$OvMS4JZkK|76=rJ&nJBMy&?oNx*0hyK#QvSm41!H3MHdLc-E9}=(;=-UIxJ_fQ!Ts3$L u8UUb%Py-N;xQ5WkZVD5~A*0gN4gmnLO3NOs|7OSl0000^rHZLbqAj_VMoBr0xxIW(n5$!0xHR<*s3 zcSD>g9M)Y`6;;P~1f{cu1_ zHnLy6`Z~*K(MEQw6c)m%W;m#|j-_Gu*p`Sowo~;**^Pl3e?~?D63|qbOd_5%fG$$!{D4YK^{XiV-3ZOW%Zca7|zX{KbJ9~l{Oj<}tAdH~6NK3;I~E*FP9IAb(v zDj6%|@2B5*0rAc_mVXL`fsh4pHPYN{Sbq0$)xP zRSTNba5`=eEvoV`4ihkG8b~LW)uje?Q#S_nMN$^J7fp<65)Kz~mmO~+Q8u+^+9EQmCnvL)Lasu7G*`Jf z4HZ*QM|3?N$gQ%DIfP7ev$d)ur^MV8R#Yu%k-gc^m&%GYFGhqR#e@N*uIB`i6NQNA zl_f!TH~dC$%YuLf$$6H<2E2Ig5B1MQ)xVk$o?3hs-=iK=o;PbU;J zpe2+6$fuG6e!kdfJoP?_>yLTeoX0J>yl$6IQN$d?a2S^_2p!VZVQa^r(7D4Us;ek`aag`s ztUu~;K~Ah!>p4-ZSGWc>>gD<+$*ZU?=ynT=T`iOd3$`Fpds;(hpAyG>thq%0$GMaV zvmjNgW}p>2imha{p6%1E8xGBHo$H8e_9>N8(gw8lU?V%X2@A(s;ncD;_Fk41)jHn- zsa zeR$FO&P(y`Qt7r!OY!bfX;Ime)Xab@pRJ@BQ(5P6?x5&Kj}9>4l_a<1=S!PQ6&+dz z#(P5=+R=u!GF_54FDmURtK3#pdOf%h>&OdpwZeYo?Na7i(K7^keBlevFY~Kh*bTq1 zQJm2)92gHrli)OnHpN9mgga1NI1QpraS;*W4ipzogJ@G+L`1j)#f8%#+7uTN5$-^7 z;WUUg#YIGfJ5XFW4WdnP5fR}I6cA6EMMQ)< zP+T|-qD^rT5#bIL7fyp{Q(QzuxC6z7(;(Uu7ZDNeKyl$Th&IJVM1(s~TsRG)O>q$s z;SLlRPJ?JuTtq~;1I2~YAleic5fSb{ap5$GHpN9mgga1NI1QpraS;*W4ipzogJ@G+ zL`1j)#f8%#+Ly#tQ+y*3CedqvBj|m<8;{>kr@i<|Y6tu4oH2MKb^R;-k%7Zv>aObiVzUi32?^T)l>kMNge;A3Jjw zY+Z8y_+OL5w{7pa9~}E(_)ml_!Wsz4TiD^Z{_joGE0J)0++&do+n?BBBI z%h{DP_rA7o*(dASW2>k3Tv#=AaYeA|gNng>9;j$Ik0k3r7OQX z@?@QTzjoU=`|l0eV;7#^@z$TS!I#BnK5~4q&hga6(eu@PE2mlJ){3j9x+-7(`h_KZ z%LnVOtXR@l_t3$q>ea#T?)oG#(|_v4@Of~>RZ}%cEL7Qp&3y0P_oh7h=)0?a`gBb< z_{=sBeYU$|`tUcmOjbRqobCyHSTps?kMGqs?Wp|rgHG_ymy_=u{-$=K{i{ll`t;x% z7e79G@+aTSBY&S7zq@MJ(YvcWm+d-w#FsTW9v>Gw(d}#N^ifZyz~%eRgHx2BpZ};6C`f@2`L9z{SJc!^6v-+uIV{ z8(!n!DrzfFbzGwchfc0*-{5#Z#jYD#yS9C)xLd*{qAWro9XpxkeS#B0GOSv Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 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 Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 zcmV+@0oVSCP)Px#;z>k7R9FdPU>F6XAuy;y;Q#;sdw@6^h}i~}!|3H0pvP|mF$g>d;(8#KpqJf) z!XBW94+AkW_zC1J0b;X3;XqnD0_f3I$i7Eop9J!$nmriF^$^e@Y2@l9pf4IIZ%07Q z3!wZAAfCy{$OvMS4JZkK|76=rJ&nJBMy&?oNx*0hyK#QvSm41!H3MHdLc-E9}=(;=-UIxJ_fQ!Ts3$L u8UUb%Py-N;xQ5WkZVD5~A*0gN4gmnLO3NOs|7OSl0000^rHZLbqAj_VMoBr0xxIW(n5$!0xHR<*s3 zcSD>g9M)Y`6;;P~1f{cu1_ zHnLy6`Z~*K(MEQw6c)m%W;m#|j-_Gu*p`Sowo~;**^Pl3e?~?D63|qbOd_5%fG$$!{D4YK^{XiV-3ZOW%Zca7|zX{KbJ9~l{Oj<}tAdH~6NK3;I~E*FP9IAb(v zDj6%|@2B5*0rAc_mVXL`fsh4pHPYN{Sbq0$)xP zRSTNba5`=eEvoV`4ihkG8b~LW)uje?Q#S_nMN$^J7fp<65)Kz~mmO~+Q8u+^+9EQmCnvL)Lasu7G*`Jf z4HZ*QM|3?N$gQ%DIfP7ev$d)ur^MV8R#Yu%k-gc^m&%GYFGhqR#e@N*uIB`i6NQNA zl_f!TH~dC$%YuLf$$6H<2E2Ig5B1MQ)xVk$o?3hs-=iK=o;PbU;J zpe2+6$fuG6e!kdfJoP?_>yLTeoX0J>yl$6IQN$d?a2S^_2p!VZVQa^r(7D4Us;ek`aag`s ztUu~;K~Ah!>p4-ZSGWc>>gD<+$*ZU?=ynT=T`iOd3$`Fpds;(hpAyG>thq%0$GMaV zvmjNgW}p>2imha{p6%1E8xGBHo$H8e_9>N8(gw8lU?V%X2@A(s;ncD;_Fk41)jHn- zsa zeR$FO&P(y`Qt7r!OY!bfX;Ime)Xab@pRJ@BQ(5P6?x5&Kj}9>4l_a<1=S!PQ6&+dz z#(P5=+R=u!GF_54FDmURtK3#pdOf%h>&OdpwZeYo?Na7i(K7^keBlevFY~Kh*bTq1 zQJm2)92gHrli)OnHpN9mgga1NI1QpraS;*W4ipzogJ@G+L`1j)#f8%#+7uTN5$-^7 z;WUUg#YIGfJ5XFW4WdnP5fR}I6cA6EMMQ)< zP+T|-qD^rT5#bIL7fyp{Q(QzuxC6z7(;(Uu7ZDNeKyl$Th&IJVM1(s~TsRG)O>q$s z;SLlRPJ?JuTtq~;1I2~YAleic5fSb{ap5$GHpN9mgga1NI1QpraS;*W4ipzogJ@G+ zL`1j)#f8%#+Ly#tQ+y*3CedqvBj|m<8;{>kr@i<|Y6tu4oH2MKb^R;-k%7Zv>aObiVzUi32?^T)l>kMNge;A3Jjw zY+Z8y_+OL5w{7pa9~}E(_)ml_!Wsz4TiD^Z{_joGE0J)0++&do+n?BBBI z%h{DP_rA7o*(dASW2>k3Tv#=AaYeA|gNng>9;j$Ik0k3r7OQX z@?@QTzjoU=`|l0eV;7#^@z$TS!I#BnK5~4q&hga6(eu@PE2mlJ){3j9x+-7(`h_KZ z%LnVOtXR@l_t3$q>ea#T?)oG#(|_v4@Of~>RZ}%cEL7Qp&3y0P_oh7h=)0?a`gBb< z_{=sBeYU$|`tUcmOjbRqobCyHSTps?kMGqs?Wp|rgHG_ymy_=u{-$=K{i{ll`t;x% z7e79G@+aTSBY&S7zq@MJ(YvcWm+d-w#FsTW9v>Gw(d}#N^ifZyz~%eRgHx2BpZ};6C`f@2`L9z{SJc!^6v-+uIV{ z8(!n!DrzfFbzGwchfc0*-{5#Z#jYD#yS9C)xLd*{qAWro9XpxkeS#B0GOSv Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 zcmV+@0oVSCP)Px#;z>k7R9FdPU>F6XAuy;y;Q#;sdw@6^h}i~}!|3H0pvP|mF$g>d;(8#KpqJf) z!XBW94+AkW_zC1J0b;X3;XqnD0_f3I$i7Eop9J!$nmriF^$^e@Y2@l9pf4IIZ%07Q z3!wZAAfCy{$OvMS4JZkK|76=rJ&nJBMy&?oNx*0hyK#QvSm41!H3MHdLc-E9}=(;=-UIxJ_fQ!Ts3$L u8UUb%Py-N;xQ5WkZVD5~A*0gN4gmnLO3NOs|7OSl0000^rHZLbqAj_VMoBr0xxIW(n5$!0xHR<*s3 zcSD>g9M)Y`6;;P~1f{cu1_ zHnLy6`Z~*K(MEQw6c)m%W;m#|j-_Gu*p`Sowo~;**^Pl3e?~?D63|qbOd_5%fG$$!{D4YK^{XiV-3ZOW%Zca7|zX{KbJ9~l{Oj<}tAdH~6NK3;I~E*FP9IAb(v zDj6%|@2B5*0rAc_mVXL`fsh4pHPYN{Sbq0$)xP zRSTNba5`=eEvoV`4ihkG8b~LW)uje?Q#S_nMN$^J7fp<65)Kz~mmO~+Q8u+^+9EQmCnvL)Lasu7G*`Jf z4HZ*QM|3?N$gQ%DIfP7ev$d)ur^MV8R#Yu%k-gc^m&%GYFGhqR#e@N*uIB`i6NQNA zl_f!TH~dC$%YuLf$$6H<2E2Ig5B1MQ)xVk$o?3hs-=iK=o;PbU;J zpe2+6$fuG6e!kdfJoP?_>yLTeoX0J>yl$6IQN$d?a2S^_2p!VZVQa^r(7D4Us;ek`aag`s ztUu~;K~Ah!>p4-ZSGWc>>gD<+$*ZU?=ynT=T`iOd3$`Fpds;(hpAyG>thq%0$GMaV zvmjNgW}p>2imha{p6%1E8xGBHo$H8e_9>N8(gw8lU?V%X2@A(s;ncD;_Fk41)jHn- zsa zeR$FO&P(y`Qt7r!OY!bfX;Ime)Xab@pRJ@BQ(5P6?x5&Kj}9>4l_a<1=S!PQ6&+dz z#(P5=+R=u!GF_54FDmURtK3#pdOf%h>&OdpwZeYo?Na7i(K7^keBlevFY~Kh*bTq1 zQJm2)92gHrli)OnHpN9mgga1NI1QpraS;*W4ipzogJ@G+L`1j)#f8%#+7uTN5$-^7 z;WUUg#YIGfJ5XFW4WdnP5fR}I6cA6EMMQ)< zP+T|-qD^rT5#bIL7fyp{Q(QzuxC6z7(;(Uu7ZDNeKyl$Th&IJVM1(s~TsRG)O>q$s z;SLlRPJ?JuTtq~;1I2~YAleic5fSb{ap5$GHpN9mgga1NI1QpraS;*W4ipzogJ@G+ zL`1j)#f8%#+Ly#tQ+y*3CedqvBj|m<8;{>kr@i<|Y6tu4oH2MKb^R;-k%7Zv>aObiVzUi32?^T)l>kMNge;A3Jjw zY+Z8y_+OL5w{7pa9~}E(_)ml_!Wsz4TiD^Z{_joGE0J)0++&do+n?BBBI z%h{DP_rA7o*(dASW2>k3Tv#=AaYeA|gNng>9;j$Ik0k3r7OQX z@?@QTzjoU=`|l0eV;7#^@z$TS!I#BnK5~4q&hga6(eu@PE2mlJ){3j9x+-7(`h_KZ z%LnVOtXR@l_t3$q>ea#T?)oG#(|_v4@Of~>RZ}%cEL7Qp&3y0P_oh7h=)0?a`gBb< z_{=sBeYU$|`tUcmOjbRqobCyHSTps?kMGqs?Wp|rgHG_ymy_=u{-$=K{i{ll`t;x% z7e79G@+aTSBY&S7zq@MJ(YvcWm+d-w#FsTW9v>Gw(d}#N^ifZyz~%eRgHx2BpZ};6C`f@2`L9z{SJc!^6v-+uIV{ z8(!n!DrzfFbzGwchfc0*-{5#Z#jYD#yS9C)xLd*{qAWro9XpxkeS#B0GOSv Z1Un+TSDiVZxgFhtww5iSL$~++{=e^be1`x4 literal 296 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 Y*7=KTle4cbhyQ}Cg^SZadR4LE|IEz-$^ZZW literal 561 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 Y*7=KTle4cbhyQ}Cg^SZadR4LE|IEz-$^ZZW literal 561 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 Y*7=KTle4cbhyQ}Cg^SZadR4LE|IEz-$^ZZW literal 561 zcmV-10?z%3P)Px$>q$gGRCodHT1!sDFc3`;pDPq@fCLLRaE4w1Rvd#BoFUz`Yd}ct6<8ov6u|}H z0B{A^gf}XUDmSrRn%YzIERAG)Cbs9j=}fFN%h-qj5g-CYfCvx)B0vP@5Gc#?9&!rV znp1KjeFQ-KJ4D(Cm~G_OYXOW=MR=#!+iW169r_H=lQp(3^|Sw0A)xAmGAY5 z^YtME1cLN~HwHj($ZI#0EHHu;2n5Lv!P-W!ow$(=0r??L#b(#KZnO0jx!@uQNZKDj z`mstti~x9D1R({sa*sc3`5cnwdyrx5m%x_&N^d#bTK0YKc@8_d2HrwWG@%qD18DN! z=PbKEMi!gsY2I?Si~(RnXQKOS0I0d^+gxM-*wC5i_S`0w#q>JYLv0^dvx++m05>^4 z89;TKce_Z7Mg;KEc4v9H8$-u0evRlQpa8)SMgXY%sFMKHI$Z$yZ@&Q`pLMSw{8Ok- zs#bF<5H5cUXPRFPyj+zC5CI}U1c(3;h=jloo(rawData.size()), &w, &h, &bpp, 0); ASSERT_EQUAL(bpp, 4, ("Incorrect texture format")); + ASSERT(glm::isPowerOfTwo(w), (w)); + ASSERT(glm::isPowerOfTwo(h), (h)); completionHandler(data, w, h); stbi_image_free(data); diff --git a/drape/symbols_texture.cpp b/drape/symbols_texture.cpp index 549f251f9c..5db348a0da 100644 --- a/drape/symbols_texture.cpp +++ b/drape/symbols_texture.cpp @@ -10,6 +10,10 @@ #include "base/string_utils.hpp" +#ifdef DEBUG +#include "3party/glm/glm/gtx/bit.hpp" +#endif + namespace dp { @@ -155,6 +159,8 @@ void LoadSymbols(string const & skinPathName, bool convertToUV, int w, h, bpp; unsigned char * data = stbi_png_load_from_memory(&rawData[0], static_cast(rawData.size()), &w, &h, &bpp, 0); ASSERT_EQUAL(bpp, 4, ("Incorrect symbols texture format")); + ASSERT(glm::isPowerOfTwo(w), (w)); + ASSERT(glm::isPowerOfTwo(h), (h)); if (width == w && height == h) {