Compare commits

...

25 Commits

Author SHA1 Message Date
Viktor Govako
e7987a14c0 [generator][tests] Added ScopedDirCleanup helper.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Kiryl Kaveryn
0c079f5120 [drape] Enable visibleViewport tracking for add place mode
It allows to dynamically update the crosshair position when the place page is dismissed.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-12-05 19:12:47 +07:00
Andrei Shkrob
723b84ca5a [map] Remove osm_opening_hours.hpp
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-12-05 19:12:47 +07:00
Viktor Govako
b4093e554d [map] Updated wiki loader.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Viktor Govako
5ab07ea610 [map] Removed Framework::m_popularityLoader.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
renderexpert
3faf052b32 Fix issue after clang-format
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-12-05 19:12:47 +07:00
Viktor Govako
6259e396f4 Redundant includes.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Viktor Govako
c968d79f4f [drape] Refactor VisualParams.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:44 +07:00
Viktor Govako
4cb6e65e81 [desktop] Show geometry type in context menu.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Viktor Govako
a962c61978 [desktop] Cancel downloading.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Kiryl Kaveryn
6cf791580f [map] Remove DeactivateMapSelection on Save osm edits
The call of `DeactivateMapSelection` is redundant because it try to close the current PP. It produces buggy behaviour on iOS the PP is closed and does not have time to open.
The PP should be only be updated using the `ActivateMapSelection`

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-12-05 19:08:18 +07:00
Viktor Govako
d1f817c3e6 [drape] Refactor UpdateVisualScale.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Jean-Baptiste
2762bd50ae [android] Rework shape of zoom buttons
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-05 16:04:10 +07:00
Leonardo Bishop
2b137a8d12 [drape] Base zoom level on distance to next turn
This commit changes the auto zoom level behaviour during navigation
to be based off the distance to the next turn, rather than naively
coupling it to the current speed. This will improve the navigation
experience during driving.

Signed-off-by: Leonardo Bishop <me@leonardobishop.net>
2025-12-05 16:04:10 +07:00
x7z4w
12ac8e8814 [search] Remove stop words
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-05 16:04:10 +07:00
gekeleda
5ab43dd67e Add Toast message at navigation start
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
2847345324 [android] Update TtsPlayer documentation, prefer en.US default locale over installed TTS locales
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
c9b3778ecc [android] Consider all langs available in TTS engine
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
593561bc06 [android] Improve TTS selection logging
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
1cfbc1a8be [android] Consider all system langs for TTS
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
ba997f6c05 [android] Fix avg speed display edge case, simplify code
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:49:00 +07:00
David Gekeler
9c9e8dac63 [android] Clarify speed average behaviour in absence of location updates
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:58 +07:00
David Gekeler
75c151bbbe [android] Fix formatting
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:56 +07:00
David Gekeler
f960b3959f [android] Add average speed calculation and change speed view to display it
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:53 +07:00
Konstantin Pastbin
24c9802a2a [planet] Update map data to 251203
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-05 12:53:12 +07:00
62 changed files with 2922 additions and 2828 deletions

View File

@@ -107,6 +107,7 @@ import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.settings.RoadType;
import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.PowerManagment;
@@ -1813,6 +1814,17 @@ public class MwmActivity extends BaseMwmFragmentActivity
return false;
}
private void deliverTtsMessage() {
if(Config.isTtsMessageDelivered())
return;
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
navigationStartMessage += TtsPlayer.INSTANCE.getLanguageDisplayName();
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
Config.setTtsMessageDelivered();
}
private boolean showStartPointNotice()
{
final RoutingController controller = RoutingController.get();
@@ -2189,6 +2201,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!showRoutingDisclaimer())
return;
deliverTtsMessage();
closeFloatingPanels();
setFullscreen(false);
RoutingController.get().start();

View File

@@ -18,6 +18,7 @@ import app.organicmaps.R;
import app.organicmaps.maplayer.MapButtonsViewModel;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Router;
import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.maplayer.traffic.TrafficManager;
import app.organicmaps.sdk.routing.CarDirection;
import app.organicmaps.sdk.routing.RoutingController;
@@ -267,16 +268,18 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
private void updateSpeedWidgets(@NonNull final RoutingInfo info)
{
final Location location = MwmApplication.from(mFrame.getContext()).getLocationHelper().getSavedLocation();
final LocationHelper locationHelper = MwmApplication.from(mFrame.getContext()).getLocationHelper();
final Location location = locationHelper.getSavedLocation();
if (location == null)
{
mSpeedLimit.setSpeedLimit(-1, false);
mCurrentSpeed.setCurrentSpeed(-1);
return;
}
final double currentAvgSpeed = locationHelper.getAverageSpeed();
final int fSpeedLimit = StringUtils.nativeFormatSpeed(info.speedLimitMps);
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(location.getSpeed());
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(currentAvgSpeed);
mSpeedLimit.setSpeedLimit(fSpeedLimit, speedLimitExceeded);
mCurrentSpeed.setCurrentSpeed(location.getSpeed());
mCurrentSpeed.setCurrentSpeed(currentAvgSpeed);
}
}

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M240,520q-17,0 -28.5,-11.5T200,480q0,-17 11.5,-28.5T240,440h480q17,0 28.5,11.5T760,480q0,17 -11.5,28.5T720,520L240,520Z"
android:pathData="M19,13H5v-2h14v2z"
android:fillColor="#ffffff"/>
</vector>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M440,520L240,520q-17,0 -28.5,-11.5T200,480q0,-17 11.5,-28.5T240,440h200v-200q0,-17 11.5,-28.5T480,200q17,0 28.5,11.5T520,240v200h200q17,0 28.5,11.5T760,480q0,17 -11.5,28.5T720,520L520,520v200q0,17 -11.5,28.5T480,760q-17,0 -28.5,-11.5T440,720v-200Z"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"
android:fillColor="@android:color/white"/>
</vector>

View File

@@ -11,14 +11,14 @@
style="@style/MwmWidget.M3.FAB.MapButton.Zoom"
android:tint="?iconTint"
app:srcCompat="@drawable/ic_plus"
app:shapeAppearance="@style/Widget.MaterialComponents.FloatingActionButton"
android:layout_marginBottom="@dimen/margin_half"
app:shapeAppearanceOverlay="@style/ShapeAppearance.MapButton.Zoom.Minus"
android:layout_marginBottom="@dimen/margin_eighth"
android:contentDescription="@string/zoom_in"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/nav_zoom_out"
style="@style/MwmWidget.M3.FAB.MapButton.Zoom"
android:tint="?iconTint"
app:srcCompat="@drawable/ic_minus"
app:shapeAppearance="@style/Widget.MaterialComponents.FloatingActionButton"
app:shapeAppearanceOverlay="@style/ShapeAppearance.MapButton.Zoom.Plus"
android:contentDescription="@string/zoom_out"/>
</LinearLayout>

View File

@@ -932,6 +932,7 @@
<string name="share_track">Share Track</string>
<string name="delete_track_dialog_title">Delete %s?</string>
<string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string>
<string name="navigation_start_tts_message">"Starting Navigation, voice instruction language: "</string>
<string name="unknown_power_output">unknown</string>
<string name="charge_socket_type2">Type 2 (no cable)</string>
<string name="charge_socket_type2_cable">Type 2 (w/ cable)</string>

View File

@@ -424,4 +424,17 @@
<item name="android:maxWidth">@dimen/map_buttons_bottom_max_width</item>
<item name="android:padding">@dimen/nav_frame_padding</item>
</style>
<style name="ShapeAppearance.MapButton.Zoom.Plus" parent="">
<item name="cornerSizeTopLeft">10%</item>
<item name="cornerSizeTopRight">10%</item>
<item name="cornerSizeBottomRight">50%</item>
<item name="cornerSizeBottomLeft">50%</item>
</style>
<style name="ShapeAppearance.MapButton.Zoom.Minus" parent="">
<item name="cornerSizeBottomLeft">10%</item>
<item name="cornerSizeBottomRight">10%</item>
<item name="cornerSizeTopLeft">50%</item>
<item name="cornerSizeTopRight">50%</item>
</style>
</resources>

View File

@@ -26,6 +26,7 @@ import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.NetworkPolicy;
import app.organicmaps.sdk.util.log.Logger;
import org.chromium.base.ObserverList;
import java.util.ArrayList;
public class LocationHelper implements BaseLocationProvider.Listener
{
@@ -35,6 +36,8 @@ public class LocationHelper implements BaseLocationProvider.Listener
private static final long AGPS_EXPIRATION_TIME_MS = 16 * 60 * 60 * 1000; // 16 hours
private static final long LOCATION_UPDATE_TIMEOUT_MS = 30 * 1000; // 30 seconds
private static final double SPEED_AVERAGING_TIME = 0.5; // 0.5 seconds
@NonNull
private final Context mContext;
@NonNull
@@ -56,6 +59,10 @@ public class LocationHelper implements BaseLocationProvider.Listener
private Handler mHandler;
private Runnable mLocationTimeoutRunnable = this::notifyLocationUpdateTimeout;
private double mTimeElapsedAtLastAverage = Double.NaN;
private float mLastAverageSpeed = Float.NaN;
private ArrayList<Float> mSpeedHistory = new ArrayList<>();
@NonNull
private final GnssStatusCompat.Callback mGnssStatusCallback = new GnssStatusCompat.Callback() {
@Override
@@ -167,6 +174,8 @@ public class LocationHelper implements BaseLocationProvider.Listener
mSavedLocation.getLongitude(), mSavedLocation.getAccuracy(),
mSavedLocation.getAltitude(), mSavedLocation.getSpeed(),
mSavedLocation.getBearing());
updateSpeedHistory();
}
private void notifyLocationUpdateTimeout()
@@ -479,4 +488,41 @@ public class LocationHelper implements BaseLocationProvider.Listener
Framework.nativeRunFirstLaunchAnimation();
}
}
private void updateSpeedHistory()
{
if (mSavedLocation == null)
{
return;
}
if (Double.isNaN(mTimeElapsedAtLastAverage))
{
mTimeElapsedAtLastAverage = mSavedLocation.getElapsedRealtimeNanos() * 1.0E-9;
}
mSpeedHistory.add(mSavedLocation.getSpeed());
}
public float getAverageSpeed()
{
if (mSavedLocation == null)
return Float.NaN;
if (Double.isNaN(mTimeElapsedAtLastAverage))
updateSpeedHistory();
double timeDiff = mSavedLocation.getElapsedRealtimeNanos() * 1.0E-9 - mTimeElapsedAtLastAverage;
if (timeDiff < SPEED_AVERAGING_TIME || mSpeedHistory.isEmpty())
{
if (!Float.isNaN(mLastAverageSpeed))
return mLastAverageSpeed;
else
return mSavedLocation.getSpeed();
}
else {
mLastAverageSpeed = mSpeedHistory.stream().reduce(0.0F, Float::sum);
mLastAverageSpeed /= mSpeedHistory.size();
mSpeedHistory.clear();
mTimeElapsedAtLastAverage = mSavedLocation.getElapsedRealtimeNanos() * 1.0E-9;
return mLastAverageSpeed;
}
}
}

View File

@@ -1,6 +1,7 @@
package app.organicmaps.sdk.sound;
import android.content.Context;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.media.AudioManager;
import android.os.Bundle;
@@ -13,6 +14,8 @@ import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat;
import androidx.core.content.ContextCompat;
import androidx.media.AudioAttributesCompat;
import androidx.media.AudioFocusRequestCompat;
@@ -23,6 +26,7 @@ import app.organicmaps.sdk.util.log.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* {@code TtsPlayer} class manages available TTS voice languages.
@@ -33,9 +37,9 @@ import java.util.Locale;
* unsupported voices are excluded.
* <p>
* At startup we check whether currently selected language is in our list of supported voices and its data is
* downloaded. If not, we check system default locale. If failed, the same check is made for English language. Finally,
* if mentioned checks fail we manually disable TTS, so the user must go to the settings and select preferred voice
* language by hand. <p> If no core supported languages can be used by the system, TTS is locked down and can not be
* downloaded. If not, we check system default locale. If failed, the same check is made for other system locales.
* If those fail too, we check for English language. Then, as a final resort, all installed TTS locales are checked.
* <p> If no core supported languages can be used by the system, TTS is locked down and can not be
* enabled and used.
*/
public enum TtsPlayer
@@ -78,6 +82,8 @@ public enum TtsPlayer
// TTS is locked down due to absence of supported languages
private boolean mUnavailable;
private LocaleListCompat mInstalledSystemLocales;
TtsPlayer() {}
private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
@@ -126,30 +132,56 @@ public enum TtsPlayer
return (lang != null && setLanguageInternal(lang));
}
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
{
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
}
private @Nullable LanguageData getSystemLanguage(List<LanguageData> langs) {
LanguageData res;
// Try default system locale
Locale defLocale = Locale.getDefault();
if (defLocale != null)
{
res = findSupportedLanguage(defLocale, langs);
res = findSupportedLanguage(defLocale, langs);
if (res != null && res.downloaded)
return res;
// Try other installed system locales
for(int i=0; i < mInstalledSystemLocales.size(); i++) {
Locale loc = mInstalledSystemLocales.get(i);
res = findSupportedLanguage(loc, langs);
if (res != null && res.downloaded)
return res;
}
return null;
}
private @Nullable LanguageData getTTSLanguage(List<LanguageData> langs) {
LanguageData res;
// Try all TTS installed languages
Set<Locale> ttsLocales = mTts.getAvailableLanguages();
for(Locale loc : ttsLocales) {
res = findSupportedLanguage(loc, langs);
if (res != null && res.downloaded)
return res;
}
return null;
}
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
{
LanguageData res;
// Try default app locale (en.US)
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
if (res != null && res.downloaded)
return res;
return null;
}
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
{
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
}
private void lockDown()
{
mUnavailable = true;
@@ -167,6 +199,10 @@ public enum TtsPlayer
// TextToSpeech.OnInitListener() can be called from a non-main thread
// on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'.
// https://github.com/organicmaps/organicmaps/issues/6903
Configuration config = context.getResources().getConfiguration();
mInstalledSystemLocales = ConfigurationCompat.getLocales(config);
mTts = new TextToSpeech(context, status -> UiThread.run(() -> {
if (status == TextToSpeech.ERROR)
{
@@ -239,6 +275,17 @@ public enum TtsPlayer
return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing);
}
public Locale getVoiceLocale()
{
return mTts.getVoice().getLocale();
}
public String getLanguageDisplayName()
{
Locale locale = getVoiceLocale();
return locale.getDisplayName(locale);
}
public void speak(String textToSpeak)
{
if (Config.TTS.isEnabled())
@@ -328,24 +375,45 @@ public enum TtsPlayer
if (outList.isEmpty())
{
// No supported languages found, lock down TTS :(
Logger.d("TtsPlayer", "No supported languages found, lock down TTS :( ");
lockDown();
return null;
}
LanguageData res = getSelectedLanguage(outList);
if (res == null || !res.downloaded)
// Selected locale is not available or not downloaded
res = getDefaultLanguage(outList);
if (res == null || !res.downloaded)
if (res != null && res.downloaded)
{
// Default locale can not be used too
Config.TTS.setEnabled(false);
return null;
Logger.d("TtsPlayer", "Selected locale " + res.internalCode + " will be used for TTS");
return res;
}
Logger.d("TtsPlayer", "Selected locale " + Config.TTS.getLanguage() + " is not available or not downloaded, trying system locales...");
res = getSystemLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "System locale " + res.internalCode + " will be used for TTS");
return res;
}
Logger.d("TtsPlayer", "None of the system locales are available, or they are not downloaded, trying default locale...");
res = getDefaultLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "Default locale " + res.internalCode + " will be used for TTS");
return res;
}
Logger.d("TtsPlayer", "Default locale " + DEFAULT_LOCALE + " can not be used either, trying all installed TTS locales...");
res = getTTSLanguage(outList);
if (res != null && res.downloaded)
{
Logger.d("TtsPlayer", "TTS locale " + res.internalCode + " will be used for TTS");
return res;
}
return res;
Logger.d("TtsPlayer", "None of the TTS engine locales are available, or they are not downloaded, disabling TTS :( ");
Config.TTS.setEnabled(false);
return null;
}
public @NonNull List<LanguageData> refreshLanguages()

View File

@@ -36,6 +36,7 @@ public final class Config
private static final String KEY_PREF_USE_GS = "UseGoogleServices";
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
private static final String KEY_MISC_TTS_MESSAGE_DELIVERED = "TtsMessageDelivered";
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
@@ -237,6 +238,16 @@ public final class Config
setBool(KEY_MISC_DISCLAIMER_ACCEPTED);
}
public static boolean isTtsMessageDelivered()
{
return getBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
}
public static void setTtsMessageDelivered()
{
setBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
}
public static boolean isLocationRequested()
{
return getBool(KEY_MISC_LOCATION_REQUESTED);

File diff suppressed because it is too large Load Diff

View File

@@ -502,12 +502,12 @@ int main(int argc, char * argv[])
if (ImGui::GetIO().WantCaptureMouse)
framework.MakeFrameActive();
if (touchActive)
#if defined(OMIM_OS_MAC)
x *= visualScale;
x *= visualScale;
y *= visualScale;
#endif
framework.TouchEvent(GetTouchEvent(framework, x, y, touchMods, df::TouchEvent::TOUCH_MOVE));
if (touchActive)
framework.TouchEvent(GetTouchEvent(framework, x, y, touchMods, df::TouchEvent::TOUCH_MOVE));
};
glfwSetCursorPosCallback(window, [](GLFWwindow *, double x, double y) { handlers.onMouseMove(x, y); });

View File

@@ -165,18 +165,16 @@ void TestAltitudesBuilding(std::vector<TPoint3DList> const & roads, bool hasAlti
AltitudeGetter & altitudeGetter)
{
classificator::Load();
Platform & platform = GetPlatform();
std::string const testDirFullPath = base::JoinPath(platform.WritableDir(), kTestDir);
std::string const testDirFullPath = base::JoinPath(GetPlatform().WritableDir(), kTestDir);
ScopedDirCleanup testScopedDir(testDirFullPath);
// Building mwm without altitude section.
LocalCountryFile country(testDirFullPath, CountryFile(kTestMwm), 1);
ScopedDir testScopedDir(kTestDir);
ScopedFile testScopedMwm(base::JoinPath(kTestDir, kTestMwm + DATA_FILE_EXTENSION), ScopedFile::Mode::Create);
BuildMwmWithoutAltitudes(roads, country);
// Adding altitude section to mwm.
auto const mwmPath = testScopedMwm.GetFullPath();
auto const mwmPath = base::JoinPath(testDirFullPath, kTestMwm + DATA_FILE_EXTENSION);
BuildRoadAltitudes(mwmPath, altitudeGetter);
// Reading from mwm and testing altitude information.

View File

@@ -64,18 +64,15 @@ std::unique_ptr<CityRoads> LoadCityRoads(LocalCountryFile const & country)
/// section and then read from it.
void TestCityRoadsBuilding(vector<uint32_t> && cityRoadFeatureIds)
{
string const writableDir = GetPlatform().WritableDir();
string const testDir = base::JoinPath(GetPlatform().WritableDir(), kTestDir);
ScopedDirCleanup scopedDir(testDir);
// Building empty mwm.
LocalCountryFile country(base::JoinPath(writableDir, kTestDir), CountryFile(kTestMwm), 0 /* version */);
ScopedDir const scopedDir(kTestDir);
string const mwmRelativePath = base::JoinPath(kTestDir, kTestMwm + DATA_FILE_EXTENSION);
ScopedFile const scopedMwm(mwmRelativePath, ScopedFile::Mode::Create);
LocalCountryFile country(testDir, CountryFile(kTestMwm), 0 /* version */);
BuildEmptyMwm(country);
// Adding city_roads section to mwm.
string const mwmFullPath = base::JoinPath(writableDir, mwmRelativePath);
string const mwmFullPath = base::JoinPath(testDir, kTestMwm + DATA_FILE_EXTENSION);
vector<uint32_t> originalCityRoadFeatureIds = cityRoadFeatureIds;
routing_builder::SerializeCityRoads(mwmFullPath, std::move(cityRoadFeatureIds));

View File

@@ -73,19 +73,18 @@ void TestMaxspeedsSection(Features const & roads, string const & maxspeedsCsvCon
FeatureIdToOsmId const & featureIdToOsmId)
{
classificator::Load();
string const testDirFullPath = base::JoinPath(GetPlatform().WritableDir(), kTestDir);
ScopedDir testScopedDir(kTestDir);
ScopedDirCleanup testScopedDir(testDirFullPath);
// Writing |maxspeedsCsvContent| to a file in |kTestDir|.
ScopedFile testScopedMaxspeedsCsv(base::JoinPath(kTestDir, kCsv), maxspeedsCsvContent);
// Writing |roads| to test mwm.
LocalCountryFile country(testDirFullPath, CountryFile(kTestMwm), 1 /* version */);
string const testMwm = kTestMwm + DATA_FILE_EXTENSION;
ScopedFile testScopedMwm(base::JoinPath(kTestDir, testMwm), ScopedFile::Mode::Create);
BuildGeometry(roads, country);
string const testMwmFullPath = base::JoinPath(testDirFullPath, testMwm);
string const testMwmFullPath = base::JoinPath(testDirFullPath, kTestMwm + DATA_FILE_EXTENSION);
// Create routing graph for test mwm.
auto const countryParentGetter = [](std::string const &) { return string(); };

View File

@@ -134,33 +134,26 @@ void LoadRestrictions(string const & mwmFilePath, vector<Restriction> & restrict
/// loads the restriction section and test loaded restrictions.
/// \param |restrictionPath| comma separated text with restrictions in osm id terms.
/// \param |osmIdsToFeatureIdContent| comma separated text with mapping from osm ids to feature ids.
void TestRestrictionBuilding(string const & restrictionPath, string const & osmIdsToFeatureIdContent,
void TestRestrictionBuilding(string const & restrictionContent, string const & osmIdsToFeatureIdContent,
unique_ptr<IndexGraph> graph, vector<Restriction> & expectedNotUTurn,
vector<RestrictionUTurnForTests> & expectedUTurn)
{
Platform & platform = GetPlatform();
string const writableDir = platform.WritableDir();
string const targetDir = base::JoinPath(GetPlatform().WritableDir(), kTestDir);
ScopedDirCleanup scopedDir(targetDir);
string const targetDir = base::JoinPath(writableDir, kTestDir);
// Building empty mwm.
LocalCountryFile country(targetDir, CountryFile(kTestMwm), 0 /* version */);
ScopedDir const scopedDir(kTestDir);
string const mwmRelativePath = base::JoinPath(kTestDir, kTestMwm + DATA_FILE_EXTENSION);
ScopedFile const scopedMwm(mwmRelativePath, ScopedFile::Mode::Create);
BuildEmptyMwm(country);
// Creating a file with restrictions.
string const restrictionRelativePath = base::JoinPath(kTestDir, kRestrictionFileName);
ScopedFile const restrictionScopedFile(restrictionRelativePath, restrictionPath);
ScopedFile const restrictionScopedFile(base::JoinPath(kTestDir, kRestrictionFileName), restrictionContent);
// Creating osm ids to feature ids mapping.
string const mappingRelativePath = base::JoinPath(kTestDir, kOsmIdsToFeatureIdsName);
ScopedFile const mappingFile(mappingRelativePath, ScopedFile::Mode::Create);
string const & osmIdsToFeatureIdFullPath = mappingFile.GetFullPath();
string const osmIdsToFeatureIdFullPath = base::JoinPath(targetDir, kOsmIdsToFeatureIdsName);
ReEncodeOsmIdsToFeatureIdsMapping(osmIdsToFeatureIdContent, osmIdsToFeatureIdFullPath);
string const restrictionFullPath = base::JoinPath(writableDir, restrictionRelativePath);
string const & mwmFullPath = scopedMwm.GetFullPath();
string const restrictionFullPath = base::JoinPath(targetDir, kRestrictionFileName);
string const mwmFullPath = base::JoinPath(targetDir, kTestMwm + DATA_FILE_EXTENSION);
// Prepare data to collector.
auto restrictionCollector =

View File

@@ -2,8 +2,6 @@
#include "indexer/data_source.hpp"
#include "base/assert.hpp"
#include "defines.hpp"
namespace descriptions
@@ -20,17 +18,28 @@ std::string Loader::GetWikiDescription(FeatureID const & featureId, std::vector<
if (!value.m_cont.IsExist(DESCRIPTIONS_FILE_TAG))
return {};
EntryPtr entry;
{
std::lock_guard<std::mutex> lock(m_mutex);
entry = m_deserializers.try_emplace(featureId.m_mwmId, std::make_shared<Entry>()).first->second;
}
// No need to have separate mutexes for each MWM since there is no concurrent Wiki pages reading.
// Pros: lock is called once and a simple logic with OnMwmDeregistered synchronization.
/// @todo Consider removing mutex at all or make wiki loading async (PlacePage info).
ASSERT(entry, ());
std::lock_guard lock(m_mutex);
Deserializer & deserializer = m_deserializers[featureId.m_mwmId];
auto readerPtr = value.m_cont.GetReader(DESCRIPTIONS_FILE_TAG);
std::lock_guard<std::mutex> lock(entry->m_mutex);
return entry->m_deserializer.Deserialize(*readerPtr.GetPtr(), featureId.m_index, langPriority);
return deserializer.Deserialize(*readerPtr.GetPtr(), featureId.m_index, langPriority);
}
void Loader::OnMwmDeregistered(platform::LocalCountryFile const & countryFile)
{
std::lock_guard lock(m_mutex);
for (auto it = m_deserializers.begin(); it != m_deserializers.end(); ++it)
{
if (it->first.IsDeregistered(countryFile))
{
m_deserializers.erase(it);
break;
}
}
}
} // namespace descriptions

View File

@@ -5,9 +5,7 @@
#include "indexer/feature_decl.hpp"
#include "indexer/mwm_set.hpp"
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
@@ -23,18 +21,11 @@ public:
explicit Loader(DataSource const & dataSource) : m_dataSource(dataSource) {}
std::string GetWikiDescription(FeatureID const & featureId, std::vector<int8_t> const & langPriority);
void OnMwmDeregistered(platform::LocalCountryFile const & countryFile);
private:
struct Entry
{
std::mutex m_mutex;
Deserializer m_deserializer;
};
using EntryPtr = std::shared_ptr<Entry>;
DataSource const & m_dataSource;
std::map<MwmSet::MwmId, EntryPtr> m_deserializers;
std::map<MwmSet::MwmId, Deserializer> m_deserializers;
std::mutex m_mutex;
};
} // namespace descriptions

View File

@@ -231,14 +231,6 @@ void SymbolsTexture::Invalidate(ref_ptr<dp::GraphicsContext> context, std::strin
Load(context, skinPathName, allocator);
}
void SymbolsTexture::Invalidate(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName,
ref_ptr<HWTextureAllocator> allocator,
std::vector<drape_ptr<HWTexture>> & internalTextures)
{
internalTextures.push_back(std::move(m_hwTexture));
Invalidate(context, skinPathName, allocator);
}
ref_ptr<Texture::ResourceInfo> SymbolsTexture::FindResource(Texture::Key const & key, bool & newResource)
{
newResource = false;

View File

@@ -36,8 +36,6 @@ public:
void Invalidate(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName,
ref_ptr<HWTextureAllocator> allocator);
void Invalidate(ref_ptr<dp::GraphicsContext> context, std::string const & skinPathName,
ref_ptr<HWTextureAllocator> allocator, std::vector<drape_ptr<HWTexture>> & internalTextures);
bool IsSymbolContained(std::string const & symbolName) const;

View File

@@ -73,6 +73,12 @@ public:
static bool IsPowerOfTwo(uint32_t width, uint32_t height);
void DeferredCleanup(std::vector<drape_ptr<HWTexture>> & toCleanup)
{
toCleanup.push_back(std::move(m_hwTexture));
Destroy();
}
protected:
void Destroy();
bool AllocateTexture(ref_ptr<dp::GraphicsContext> context, ref_ptr<HWTextureAllocator> allocator);

View File

@@ -87,6 +87,10 @@ drape_ptr<Texture> CreateArrowTexture(ref_ptr<dp::GraphicsContext> context,
useDefaultResourceFolder ? StaticTexture::kDefaultResource : std::string(),
dp::TextureFormat::RGBA8, textureAllocator, true /* allowOptional */);
}
// There is no "arrow-texture.png".
// BackendRenderer::m_arrow3dPreloadedData mesh is used by default.
/// @todo Texture arrow is still present in case if somebody wants to use it?
return make_unique_dp<StaticTexture>(context, "arrow-texture.png", StaticTexture::kDefaultResource,
dp::TextureFormat::RGBA8, textureAllocator, true /* allowOptional */);
}
@@ -315,39 +319,7 @@ void TextureManager::Init(ref_ptr<dp::GraphicsContext> context, Params const & p
m_smaaSearchTexture = make_unique_dp<StaticTexture>(context, "smaa-search.png", StaticTexture::kDefaultResource,
dp::TextureFormat::Red, make_ref(m_textureAllocator));
// Initialize patterns (reserved ./data/patterns.txt lines count).
std::set<PenPatternT> patterns;
double const visualScale = params.m_visualScale;
uint32_t rowsCount = 0;
impl::ParsePatternsList(params.m_patterns, [&](buffer_vector<double, 8> const & pattern)
{
PenPatternT toAdd;
for (double d : pattern)
toAdd.push_back(PatternFloat2Pixel(d * visualScale));
if (!patterns.insert(toAdd).second)
return;
if (IsTrianglePattern(toAdd))
{
rowsCount = rowsCount + toAdd[2] + toAdd[3];
}
else
{
ASSERT_EQUAL(toAdd.size(), 2, ());
++rowsCount;
}
});
m_stipplePenTexture = make_unique_dp<StipplePenTexture>(StipplePenTextureSize(rowsCount, m_maxTextureSize),
make_ref(m_textureAllocator));
LOG(LDEBUG, ("Patterns texture size =", m_stipplePenTexture->GetWidth(), m_stipplePenTexture->GetHeight()));
ref_ptr<StipplePenTexture> stipplePenTex = make_ref(m_stipplePenTexture);
for (auto const & p : patterns)
stipplePenTex->ReservePattern(p);
InitStipplePen(params);
// Initialize colors (reserved ./data/colors.txt lines count).
std::vector<dp::Color> colors;
@@ -380,25 +352,73 @@ void TextureManager::Init(ref_ptr<dp::GraphicsContext> context, Params const & p
m_nothingToUpload.clear();
}
void TextureManager::InitStipplePen(Params const & params)
{
// Initialize patterns (reserved ./data/patterns.txt lines count).
std::set<PenPatternT> patterns;
uint32_t rowsCount = 0;
impl::ParsePatternsList(params.m_patterns, [&](buffer_vector<double, 8> const & pattern)
{
PenPatternT toAdd;
for (double d : pattern)
toAdd.push_back(PatternFloat2Pixel(d * params.m_visualScale));
if (!patterns.insert(toAdd).second)
return;
if (IsTrianglePattern(toAdd))
{
rowsCount = rowsCount + toAdd[2] + toAdd[3];
}
else
{
ASSERT_EQUAL(toAdd.size(), 2, ());
++rowsCount;
}
});
m_stipplePenTexture = make_unique_dp<StipplePenTexture>(StipplePenTextureSize(rowsCount, m_maxTextureSize),
make_ref(m_textureAllocator));
LOG(LDEBUG, ("Patterns texture size =", m_stipplePenTexture->GetWidth(), m_stipplePenTexture->GetHeight()));
ref_ptr<StipplePenTexture> stipplePenTex = make_ref(m_stipplePenTexture);
for (auto const & p : patterns)
stipplePenTex->ReservePattern(p);
}
void TextureManager::OnSwitchMapStyle(ref_ptr<dp::GraphicsContext> context)
{
CHECK(m_isInitialized, ());
bool const isVulkan = context->GetApiVersion() == dp::ApiVersion::Vulkan;
// Here we need invalidate only textures which can be changed in map style switch.
// Now we update only symbol textures, if we need update other textures they must be added here.
// For Vulkan we use m_texturesToCleanup to defer textures destroying.
for (auto const & m_symbolTexture : m_symbolTextures)
for (auto const & texture : m_symbolTextures)
{
ref_ptr<SymbolsTexture> symbolsTexture = make_ref(m_symbolTexture);
ASSERT(symbolsTexture != nullptr, ());
ref_ptr<SymbolsTexture> symbolsTexture = make_ref(texture);
if (isVulkan)
symbolsTexture->DeferredCleanup(m_texturesToCleanup);
if (context->GetApiVersion() != dp::ApiVersion::Vulkan)
symbolsTexture->Invalidate(context, m_resPostfix, make_ref(m_textureAllocator));
else
symbolsTexture->Invalidate(context, m_resPostfix, make_ref(m_textureAllocator), m_texturesToCleanup);
symbolsTexture->Invalidate(context, m_resPostfix, make_ref(m_textureAllocator));
}
}
void TextureManager::OnVisualScaleChanged(ref_ptr<dp::GraphicsContext> context, Params const & params)
{
m_resPostfix = params.m_resPostfix;
OnSwitchMapStyle(context);
if (context->GetApiVersion() == dp::ApiVersion::Vulkan)
m_stipplePenTexture->DeferredCleanup(m_texturesToCleanup);
InitStipplePen(params);
}
void TextureManager::InvalidateArrowTexture(ref_ptr<dp::GraphicsContext> context,
std::string const & texturePath /* = {} */,
bool useDefaultResourceFolder /* = false */)
@@ -416,10 +436,13 @@ void TextureManager::ApplyInvalidatedStaticTextures()
}
}
void TextureManager::GetTexturesToCleanup(std::vector<drape_ptr<HWTexture>> & textures)
std::vector<drape_ptr<HWTexture>> TextureManager::GetTexturesToCleanup()
{
CHECK(m_isInitialized, ());
std::swap(textures, m_texturesToCleanup);
auto res = std::move(m_texturesToCleanup);
m_texturesToCleanup.clear();
return res;
}
bool TextureManager::GetSymbolRegionSafe(std::string const & symbolName, SymbolRegion & region)

View File

@@ -77,7 +77,9 @@ public:
void Init(ref_ptr<dp::GraphicsContext> context, Params const & params);
void OnSwitchMapStyle(ref_ptr<dp::GraphicsContext> context);
void GetTexturesToCleanup(std::vector<drape_ptr<HWTexture>> & textures);
void OnVisualScaleChanged(ref_ptr<dp::GraphicsContext> context, Params const & params);
std::vector<drape_ptr<HWTexture>> GetTexturesToCleanup();
bool GetSymbolRegionSafe(std::string const & symbolName, SymbolRegion & region);
void GetSymbolRegion(std::string const & symbolName, SymbolRegion & region);
@@ -121,6 +123,8 @@ public:
ref_ptr<HWTextureAllocator> GetTextureAllocator() const;
private:
void InitStipplePen(Params const & params);
struct GlyphGroup
{
std::set<GlyphFontAndId> m_glyphKeys;

View File

@@ -525,9 +525,11 @@ void ApplyPointFeature::ProcessPointRules(SymbolRuleProto const * symbolRule, Ca
params.m_depth = PriorityToDepth(symbolRule->priority(), drule::symbol, 0);
params.m_symbolName = symbolRule->name();
ASSERT_GREATER_OR_EQUAL(symbolRule->min_distance(), 0, ());
// Where 0.1 comes from: https://github.com/organicmaps/organicmaps/pull/649
auto const & vp = df::VisualParams::Instance();
params.m_extendingSize =
static_cast<uint32_t>(vp.GetVisualScale() * symbolRule->min_distance() * vp.GetPoiExtendScale());
params.m_extendingSize = static_cast<uint32_t>(vp.GetVisualScale() * symbolRule->min_distance() * 0.1);
params.m_posZ = m_posZ;
params.m_hasArea = HasArea();
params.m_prioritized = createdByEditor;

View File

@@ -17,8 +17,6 @@
#include "drape/support_manager.hpp"
#include "drape/texture_manager.hpp"
#include "indexer/scales.hpp"
#include "platform/platform.hpp"
#include "base/file_name_utils.hpp"
@@ -355,18 +353,37 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
m_trafficGenerator->InvalidateTexturesCache();
m_transitBuilder->RebuildSchemes(m_context, m_texMng);
// For Vulkan we initialize deferred cleaning up.
if (m_context->GetApiVersion() == dp::ApiVersion::Vulkan)
{
std::vector<drape_ptr<dp::HWTexture>> textures;
m_texMng->GetTexturesToCleanup(textures);
if (!textures.empty())
{
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<CleanupTexturesMessage>(std::move(textures)), MessagePriority::Normal);
}
}
CleanupTextures();
break;
}
case Message::Type::VisualScaleChanged:
{
ref_ptr<VisualScaleChangedMessage> msg = message;
msg->FilterDependentMessages();
CHECK(m_context != nullptr, ());
dp::TextureManager::Params params;
params.m_resPostfix = VisualParams::Instance().GetResourcePostfix();
params.m_visualScale = df::VisualParams::Instance().GetVisualScale();
#ifdef BUILD_DESIGNER
params.m_patterns = "patterns_design.txt";
#else
params.m_patterns = "patterns.txt";
#endif // BUILD_DESIGNER
m_texMng->OnVisualScaleChanged(m_context, params);
RecacheMapShapes();
RecacheGui(m_lastWidgetsInfo, false /* needResetOldGui */);
#ifdef RENDER_DEBUG_INFO_LABELS
RecacheDebugLabels();
#endif
m_trafficGenerator->InvalidateTexturesCache();
m_transitBuilder->RebuildSchemes(m_context, m_texMng);
CleanupTextures();
break;
}
@@ -611,21 +628,8 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
m_arrow3dPreloadedData = Arrow3d::PreloadMesh(m_arrow3dCustomDecl, m_texMng);
}
// Recache map shapes.
RecacheMapShapes();
// For Vulkan we initialize deferred cleaning up.
if (m_context->GetApiVersion() == dp::ApiVersion::Vulkan)
{
std::vector<drape_ptr<dp::HWTexture>> textures;
m_texMng->GetTexturesToCleanup(textures);
if (!textures.empty())
{
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<CleanupTexturesMessage>(std::move(textures)), MessagePriority::Normal);
}
}
CleanupTextures();
break;
}
@@ -772,6 +776,18 @@ void BackendRenderer::RecacheMapShapes()
m_commutator->PostMessage(ThreadsCommutator::RenderThread, std::move(msg), MessagePriority::Normal);
}
void BackendRenderer::CleanupTextures()
{
// For Vulkan we initialize deferred cleaning up.
if (m_context->GetApiVersion() == dp::ApiVersion::Vulkan)
{
auto textures = m_texMng->GetTexturesToCleanup();
if (!textures.empty())
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<CleanupTexturesMessage>(std::move(textures)), MessagePriority::Normal);
}
}
void BackendRenderer::FlushGeometry(TileKey const & key, dp::RenderState const & state,
drape_ptr<dp::RenderBucket> && buffer)
{

View File

@@ -83,6 +83,7 @@ private:
void RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool needResetOldGui);
void RecacheChoosePositionMark();
void RecacheMapShapes();
void CleanupTextures();
#ifdef RENDER_DEBUG_INFO_LABELS
void RecacheDebugLabels();

View File

@@ -441,12 +441,13 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
MessagePriority::Normal);
}
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo),
MessagePriority::Normal);
m_threadCommutator->PostMessage(
ThreadsCommutator::RenderThread,
make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
MessagePriority::Normal);
}
void DrapeEngine::SwitchMyPositionNextMode()
@@ -896,10 +897,8 @@ void DrapeEngine::UpdateVisualScale(double vs, bool needStopRendering)
if (needStopRendering)
SetRenderingEnabled();
RecacheGui(false);
RecacheMapShapes();
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<RecoverContextDependentResourcesMessage>(), MessagePriority::Normal);
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp<UpdateVisualScaleMessage>(),
MessagePriority::High);
}
void DrapeEngine::UpdateMyPositionRoutingOffset(bool useDefault, int offsetY)

View File

@@ -154,7 +154,8 @@ public:
void UpdateMapStyle();
void SetCompassInfo(location::CompassInfo const & info);
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo);
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo);
void SwitchMyPositionNextMode();
void LoseLocation();
void StopLocationFollow();

View File

@@ -438,7 +438,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
#endif
ref_ptr<GpsInfoMessage> msg = message;
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen());
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
if (info.HasDistanceFromBegin())
@@ -639,51 +640,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::Type::RecoverContextDependentResources:
{
UpdateContextDependentResources();
break;
}
case Message::Type::RecoverContextDependentResources: UpdateContextDependentResources(); break;
case Message::Type::UpdateMapStyle:
{
#ifdef BUILD_DESIGNER
classificator::Load();
#endif // BUILD_DESIGNER
case Message::Type::UpdateMapStyle: UpdateAll<SwitchMapStyleMessage>(); break;
// Clear all graphics.
for (RenderLayer & layer : m_layers)
{
layer.m_renderGroups.clear();
layer.m_isDirty = false;
}
// Must be recreated on map style changing.
CHECK(m_context != nullptr, ());
m_transitBackground = make_unique_dp<ScreenQuadRenderer>(m_context);
// Invalidate read manager.
{
BaseBlockingMessage::Blocker blocker;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<InvalidateReadManagerRectMessage>(blocker), MessagePriority::Normal);
blocker.Wait();
}
// Delete all messages which can contain render states (and textures references inside).
auto f = [this]() { InstantMessageFilter([](ref_ptr<Message> msg) { return msg->ContainsRenderState(); }); };
// Notify backend renderer and wait for completion.
{
BaseBlockingMessage::Blocker blocker;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<SwitchMapStyleMessage>(blocker, std::move(f)), MessagePriority::Normal);
blocker.Wait();
}
UpdateContextDependentResources();
break;
}
case Message::Type::VisualScaleChanged: UpdateAll<VisualScaleChangedMessage>(); break;
case Message::Type::AllowAutoZoom:
{
@@ -809,7 +770,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
zoom = scales::GetAddNewPlaceScale();
AddUserEvent(make_unique_dp<SetCenterEvent>(
pt ? *pt : m_userEventStream.GetCurrentScreen().GlobalRect().Center(), zoom, true /* isAnim */,
false /* trackVisibleViewport */, nullptr /* parallelAnimCreator */));
true /* trackVisibleViewport */, nullptr /* parallelAnimCreator */));
}
else
{
@@ -1022,6 +983,46 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
}
}
template <class MessageT>
void FrontendRenderer::UpdateAll()
{
#ifdef BUILD_DESIGNER
classificator::Load();
#endif // BUILD_DESIGNER
// Clear all graphics.
for (RenderLayer & layer : m_layers)
{
layer.m_renderGroups.clear();
layer.m_isDirty = false;
}
// Must be recreated on map style changing.
CHECK(m_context != nullptr, ());
m_transitBackground = make_unique_dp<ScreenQuadRenderer>(m_context);
// Invalidate read manager.
{
BaseBlockingMessage::Blocker blocker;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<InvalidateReadManagerRectMessage>(blocker), MessagePriority::Normal);
blocker.Wait();
}
// Delete all messages which can contain render states (and textures references inside).
auto f = [this]() { InstantMessageFilter([](ref_ptr<Message> msg) { return msg->ContainsRenderState(); }); };
// Notify backend renderer and wait for completion.
{
BaseBlockingMessage::Blocker blocker;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp<MessageT>(blocker, std::move(f)),
MessagePriority::Normal);
blocker.Wait();
}
UpdateContextDependentResources();
}
std::unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine()
{
return std::make_unique<Routine>(*this);

View File

@@ -247,6 +247,9 @@ private:
void ReleaseResources();
void UpdateContextDependentResources();
template <class MessageT>
void UpdateAll();
void BeginUpdateOverlayTree(ScreenBase const & modelView);
void UpdateOverlayTree(ScreenBase const & modelView, drape_ptr<RenderGroup> & renderGroup);
void EndUpdateOverlayTree();

View File

@@ -103,6 +103,7 @@ std::string DebugPrint(Message::Type msgType)
case Message::Type::EnableIsolines: return "EnableIsolines";
case Message::Type::OnEnterBackground: return "OnEnterBackground";
case Message::Type::Arrow3dRecache: return "Arrow3dRecache";
case Message::Type::VisualScaleChanged: return "VisualScaleChanged";
}
ASSERT(false, ("Unknown message type."));
return "Unknown type";

View File

@@ -103,7 +103,8 @@ public:
NotifyGraphicsReady,
EnableIsolines,
OnEnterBackground,
Arrow3dRecache
Arrow3dRecache,
VisualScaleChanged,
};
virtual ~Message() = default;

View File

@@ -1,7 +1,6 @@
#pragma once
#include "drape_frontend/circles_pack_shape.hpp"
#include "drape_frontend/color_constants.hpp"
#include "drape_frontend/custom_features_context.hpp"
#include "drape_frontend/drape_api.hpp"
#include "drape_frontend/drape_api_builder.hpp"
@@ -14,8 +13,7 @@
#include "drape_frontend/overlay_batcher.hpp"
#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/render_node.hpp"
#include "drape_frontend/render_state_extension.hpp"
#include "drape_frontend/route_builder.hpp"
#include "drape_frontend/route_shape.hpp"
#include "drape_frontend/selection_shape.hpp"
#include "drape_frontend/tile_utils.hpp"
#include "drape_frontend/traffic_generator.hpp"
@@ -26,13 +24,10 @@
#include "drape/pointers.hpp"
#include "drape/render_bucket.hpp"
#include "drape/viewport.hpp"
#include "platform/location.hpp"
#include "geometry/polyline2d.hpp"
#include "geometry/rect2d.hpp"
#include "geometry/screenbase.hpp"
#include "geometry/triangle2d.hpp"
#include <condition_variable>
@@ -40,7 +35,6 @@
#include <map>
#include <mutex>
#include <optional>
#include <utility>
#include <vector>
namespace df
@@ -481,9 +475,12 @@ private:
class GpsInfoMessage : public Message
{
public:
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo)
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
location::RouteMatchingInfo const & routeInfo)
: m_info(info)
, m_isNavigable(isNavigable)
, m_distToNextTurn(distToNextTurn)
, m_speedLimit(speedLimit)
, m_routeInfo(routeInfo)
{}
@@ -491,11 +488,15 @@ public:
location::GpsInfo const & GetInfo() const { return m_info; }
bool IsNavigable() const { return m_isNavigable; }
double const & GetSpeedLimit() const { return m_speedLimit; }
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
private:
location::GpsInfo const m_info;
bool const m_isNavigable;
double const m_distToNextTurn;
double const m_speedLimit;
location::RouteMatchingInfo const m_routeInfo;
};
@@ -730,6 +731,12 @@ public:
Type GetType() const override { return Type::UpdateMapStyle; }
};
class UpdateVisualScaleMessage : public Message
{
public:
Type GetType() const override { return Type::VisualScaleChanged; }
};
class FollowRouteMessage : public Message
{
public:
@@ -776,6 +783,14 @@ private:
FilterMessagesHandler m_filterMessagesHandler;
};
class VisualScaleChangedMessage : public SwitchMapStyleMessage
{
public:
using SwitchMapStyleMessage::SwitchMapStyleMessage;
Type GetType() const override { return Type::VisualScaleChanged; }
};
class InvalidateMessage : public Message
{
public:

View File

@@ -56,32 +56,18 @@ inline double GetVisualScale()
return df::VisualParams::Instance().GetVisualScale();
}
// Calculate zoom value in meters per pixel
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
{
using TSpeedScale = std::pair<double, double>;
static std::array<TSpeedScale, 6> const scales3d = {{
{20.0, 0.25},
{40.0, 0.75},
{60.0, 1.50},
{75.0, 2.50},
{85.0, 3.75},
{95.0, 6.00},
static std::array<TSpeedScale, 2> const scales2d = {{
{0.0, 1.75}, {77.0, 4.50} // 48 mph
}};
static std::array<TSpeedScale, 2> const scales3d = {{{0.0, 1.00}, {77.0, 4.50}}};
static std::array<TSpeedScale, 6> const scales2d = {{
{20.0, 0.70},
{40.0, 1.25},
{60.0, 2.25},
{75.0, 3.00},
{85.0, 3.75},
{95.0, 6.00},
}};
std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
std::array<TSpeedScale, 6> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
double constexpr kDefaultSpeedKmpH = 80.0;
double const speedKmpH = speedMpS >= 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedKmpH;
double constexpr kDefaultSpeedLimitKmpH = 50.0;
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
size_t i = 0;
for (size_t sz = scales.size(); i < sz; ++i)
@@ -92,20 +78,64 @@ double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
if (i == 0)
return scales.front().second / vs;
if (i == scales.size())
return scales.back().second / vs;
double const minSpeed = scales[i - 1].first;
double const maxSpeed = scales[i].first;
double const k = (speedKmpH - minSpeed) / (maxSpeed - minSpeed);
return scales[i - 1].second / vs;
}
double const minScale = scales[i - 1].second;
double const maxScale = scales[i].second;
double CalculateZoomByDistanceToTurn(double distance, bool isPerspectiveAllowed)
{
using TSpeedScale = std::pair<double, double>;
static std::array<TSpeedScale, 5> const scales2d = {{
{200, 0.50},
{500, 0.80}, // 0.3 mi
{1200, 1.75}, // 0.75 mi
{2000, 3.50}, // 1.2 mi
{5000, 6.50} // 3 mi
}};
static std::array<TSpeedScale, 5> const scales3d = {{
{200, 0.25},
{500, 0.60}, // 0.3 mi
{1200, 1.25}, // 0.75 mi
{2000, 3.50}, // 1.2 mi
{5000, 6.50} // 3 mi
}};
std::array<TSpeedScale, 5> const & scale = isPerspectiveAllowed ? scales3d : scales2d;
double constexpr kDefaultDistance = 2000;
double const distanceM = distance >= 0 ? distance : kDefaultDistance;
size_t i = 0;
for (size_t sz = scale.size(); i < sz; ++i)
if (scale[i].first >= distanceM)
break;
double const vs = GetVisualScale();
if (i == 0)
return scale.front().second / vs;
if (i == scale.size())
return scale.back().second / vs;
double const minDist = scale[i - 1].first;
double const maxDist = scale[i].first;
double const k = (distanceM - minDist) / (maxDist - minDist);
double const minScale = scale[i - 1].second;
double const maxScale = scale[i].second;
double const zoom = minScale + k * (maxScale - minScale);
return zoom / vs;
}
double CalculateAutoZoom(double speedMpS, double distanceToTurn, bool isPerspectiveAllowed)
{
double const zoomByDistance = CalculateZoomByDistanceToTurn(distanceToTurn, isPerspectiveAllowed);
double const zoomByMaxSpeed = CalculateZoomByMaxSpeed(speedMpS, isPerspectiveAllowed);
return std::min(zoomByDistance, zoomByMaxSpeed);
}
void ResetNotification(uint64_t & notifyId)
{
notifyId = DrapeNotifier::kInvalidId;
@@ -395,7 +425,8 @@ void MyPositionController::NextMode(ScreenBase const & screen)
}
}
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen)
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
double speedLimit, ScreenBase const & screen)
{
m2::PointD const oldPos = GetDrawablePosition();
double const oldAzimut = GetDrawableAzimut();
@@ -407,11 +438,13 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
m_errorRadius = rect.SizeX() * 0.5;
m_horizontalAccuracy = info.m_horizontalAccuracy;
if (info.m_speed > 0.0)
if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
{
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
m_autoScale2d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, false /* isPerspectiveAllowed */);
m_autoScale3d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, true /* isPerspectiveAllowed */);
m_autoScale2d =
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
m_autoScale3d =
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
}
else
{

View File

@@ -117,7 +117,8 @@ public:
void OnEnterBackground();
void OnCompassTapped();
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen);
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
ScreenBase const & screen);
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,

View File

@@ -4,14 +4,8 @@
#include "indexer/scales.hpp"
#include "platform/settings.hpp"
#include "geometry/angles.hpp"
#include "geometry/distance_on_sphere.hpp"
#include "geometry/point2d.hpp"
#include "geometry/transformations.hpp"
#include "base/logging.hpp"
namespace df
{

View File

@@ -2,8 +2,6 @@
#include "geometry/screenbase.hpp"
#include "base/matrix.hpp"
namespace df
{
extern double const kDefault3dScale;

View File

@@ -1,9 +1,5 @@
#include "screen_operations.hpp"
#include "drape_frontend/animation/interpolators.hpp"
#include "drape_frontend/animation/linear_animation.hpp"
#include "drape_frontend/animation/scale_animation.hpp"
#include "drape_frontend/animation_constants.hpp"
#include "drape_frontend/visual_params.hpp"
#include "indexer/scales.hpp"

View File

@@ -1,5 +1,9 @@
#include "drape_frontend/visual_params.hpp"
#include "indexer/scales.hpp"
#include "coding/point_coding.hpp" // kMwmPointAccuracy
#include "geometry/mercator.hpp"
#include "base/assert.hpp"
@@ -12,21 +16,11 @@
#include <algorithm>
#include <cmath>
#include <limits>
#include <utility>
namespace df
{
using VisualScale = std::pair<std::string, double>;
#ifdef DEBUG
static bool g_isInited = false;
#define RISE_INITED g_isInited = true
#define ASSERT_INITED ASSERT(g_isInited, ())
#else
#define RISE_INITED
#define ASSERT_INITED
#endif
VisualParams & VisualParams::Instance()
{
static VisualParams vizParams;
@@ -35,7 +29,8 @@ VisualParams & VisualParams::Instance()
void VisualParams::Init(double vs, uint32_t tileSize)
{
ASSERT_LESS_OR_EQUAL(vs, kMaxVisualScale, ());
CHECK(vs >= 1.0 && vs <= kMaxVisualScale, (vs));
CHECK(tileSize >= 32, (tileSize));
VisualParams & vizParams = Instance();
vizParams.m_tileSize = tileSize;
@@ -47,35 +42,34 @@ void VisualParams::Init(double vs, uint32_t tileSize)
else
vizParams.m_glyphVisualParams = {0.5f, 0.06f, 0.2f, 0.01f, 0.49f, 0.04f};
RISE_INITED;
vizParams.m_isInited = true;
LOG(LINFO, ("Visual scale =", vs, "; Tile size =", tileSize, "; Resources =", GetResourcePostfix(vs)));
}
double VisualParams::GetFontScale() const
{
ASSERT_INITED;
ASSERT(m_isInited, ());
return m_fontScale;
}
void VisualParams::SetFontScale(double fontScale)
{
ASSERT_INITED;
ASSERT(m_isInited, ());
m_fontScale = math::Clamp(fontScale, 0.5, 2.0);
}
void VisualParams::SetVisualScale(double visualScale)
void VisualParams::SetVisualScale(double vs)
{
ASSERT_INITED;
ASSERT_LESS_OR_EQUAL(visualScale, kMaxVisualScale, ());
m_visualScale = visualScale;
ASSERT(m_isInited, ());
CHECK(vs >= 1.0 && vs <= kMaxVisualScale, (vs));
m_visualScale = vs;
LOG(LINFO, ("Visual scale =", visualScale));
LOG(LINFO, ("Visual scale =", vs));
}
std::string const & VisualParams::GetResourcePostfix(double visualScale)
{
ASSERT_INITED;
static VisualScale postfixes[] = {
/// @todo Not used in mobile because of minimal visual scale (@see visual_scale.hpp)
{"mdpi", kMdpiScale},
@@ -103,52 +97,61 @@ std::string const & VisualParams::GetResourcePostfix(double visualScale)
std::string const & VisualParams::GetResourcePostfix() const
{
ASSERT_INITED;
ASSERT(m_isInited, ());
return VisualParams::GetResourcePostfix(m_visualScale);
}
double VisualParams::GetVisualScale() const
{
ASSERT_INITED;
ASSERT(m_isInited, ());
return m_visualScale;
}
double VisualParams::GetPoiExtendScale() const
{
ASSERT_INITED;
return m_poiExtendScale;
}
uint32_t VisualParams::GetTileSize() const
{
ASSERT_INITED;
CHECK(m_isInited, ());
return m_tileSize;
}
uint32_t VisualParams::GetTouchRectRadius() const
{
<<<<<<< HEAD
ASSERT_INITED;
float constexpr kRadiusInPixels = 20.0f;
=======
ASSERT(m_isInited, ());
float const kRadiusInPixels = 20.0f;
>>>>>>> 9cff373c8 ([drape] Refactor VisualParams.)
return static_cast<uint32_t>(kRadiusInPixels * GetVisualScale());
}
double VisualParams::GetDragThreshold() const
{
<<<<<<< HEAD
ASSERT_INITED;
double constexpr kDragThresholdInPixels = 10.0;
=======
ASSERT(m_isInited, ());
double const kDragThresholdInPixels = 10.0;
>>>>>>> 9cff373c8 ([drape] Refactor VisualParams.)
return kDragThresholdInPixels * GetVisualScale();
}
double VisualParams::GetScaleThreshold() const
{
<<<<<<< HEAD
ASSERT_INITED;
double constexpr kScaleThresholdInPixels = 2.0;
=======
ASSERT(m_isInited, ());
double const kScaleThresholdInPixels = 2.0;
>>>>>>> 9cff373c8 ([drape] Refactor VisualParams.)
return kScaleThresholdInPixels * GetVisualScale();
}
VisualParams::GlyphVisualParams const & VisualParams::GetGlyphVisualParams() const
{
ASSERT_INITED;
ASSERT(m_isInited, ());
return m_glyphVisualParams;
}
@@ -178,8 +181,7 @@ int GetTileScaleBase(ScreenBase const & s)
int GetTileScaleBase(m2::RectD const & r)
{
double const sz = std::max(r.SizeX(), r.SizeY());
ASSERT_GREATER(sz, 0., ("Rect should not be a point:", r));
double const sz = std::max(std::max(r.SizeX(), r.SizeY()), kMwmPointAccuracy);
return std::max(1, math::iround(std::log2(mercator::Bounds::kRangeX / sz)));
}
@@ -190,7 +192,7 @@ double GetTileScaleBase(double drawScale)
int GetTileScaleIncrement(uint32_t tileSize, double visualScale)
{
return static_cast<int>(std::log2(tileSize / 256.0 / visualScale));
return math::iround(std::log2(tileSize / 256.0 / visualScale));
}
int GetTileScaleIncrement()
@@ -257,10 +259,18 @@ uint32_t CalculateTileSize(uint32_t screenWidth, uint32_t screenHeight)
#endif
}
namespace
{
double GetDrawTileScale(double baseScale)
{
return baseScale + GetTileScaleIncrement();
}
int GetDrawTileScale(int baseScale, uint32_t tileSize, double visualScale)
{
return std::max(1, baseScale + GetTileScaleIncrement(tileSize, visualScale));
return baseScale + GetTileScaleIncrement(tileSize, visualScale);
}
} // namespace
int GetDrawTileScale(ScreenBase const & s, uint32_t tileSize, double visualScale)
{
@@ -272,17 +282,6 @@ int GetDrawTileScale(m2::RectD const & r, uint32_t tileSize, double visualScale)
return GetDrawTileScale(GetTileScaleBase(r), tileSize, visualScale);
}
int GetDrawTileScale(int baseScale)
{
VisualParams const & p = VisualParams::Instance();
return GetDrawTileScale(baseScale, p.GetTileSize(), p.GetVisualScale());
}
double GetDrawTileScale(double baseScale)
{
return std::max(1.0, baseScale + GetTileScaleIncrement());
}
int GetDrawTileScale(ScreenBase const & s)
{
VisualParams const & p = VisualParams::Instance();

View File

@@ -1,15 +1,10 @@
#pragma once
#include "indexer/scales.hpp"
#include "geometry/rect2d.hpp"
#include "geometry/screenbase.hpp"
#include "base/macros.hpp"
#include <atomic>
#include <cstdint>
#include <string>
#include <vector>
namespace df
{
@@ -36,8 +31,6 @@ public:
std::string const & GetResourcePostfix() const;
double GetVisualScale() const;
/// This is a scale factor to decrease extending of bbox for POI icons. It could be removed with new style
double GetPoiExtendScale() const;
uint32_t GetTileSize() const;
/// How many pixels around touch point are used to get bookmark or POI in consideration of visual scale.
@@ -62,7 +55,7 @@ public:
void SetFontScale(double fontScale);
// This method can be called ONLY if rendering is disabled.
void SetVisualScale(double visualScale);
void SetVisualScale(double vs);
private:
VisualParams() = default;
@@ -71,8 +64,8 @@ private:
uint32_t m_tileSize = 0;
double m_visualScale = 0.0;
double m_poiExtendScale = 0.1; // Found empirically.
std::atomic<double> m_fontScale = 1.0;
double m_fontScale = 1.0;
bool m_isInited = false;
DISALLOW_COPY_AND_MOVE(VisualParams);
};
@@ -89,11 +82,8 @@ double GetTileScaleBase(double drawScale);
int GetTileScaleIncrement(uint32_t tileSize, double visualScale);
int GetTileScaleIncrement();
int GetDrawTileScale(int baseScale, uint32_t tileSize, double visualScale);
int GetDrawTileScale(ScreenBase const & s, uint32_t tileSize, double visualScale);
int GetDrawTileScale(m2::RectD const & r, uint32_t tileSize, double visualScale);
int GetDrawTileScale(int baseScale);
double GetDrawTileScale(double baseScale);
int GetDrawTileScale(ScreenBase const & s);
int GetDrawTileScale(m2::RectD const & r);

View File

@@ -5,8 +5,6 @@ set(SRC
altitude_loader.hpp
brands_holder.cpp
brands_holder.hpp
caching_rank_table_loader.cpp
caching_rank_table_loader.hpp
categories_holder.cpp
categories_holder.hpp
categories_holder_loader.cpp
@@ -155,7 +153,6 @@ file(COPY ${OTHER_FILES} DESTINATION ${CMAKE_BINARY_DIR})
omim_add_library(${PROJECT_NAME} ${SRC})
target_link_libraries(${PROJECT_NAME}
search # search::DummyRankTable in CachingRankTableLoader
platform
geometry
protobuf

View File

@@ -1,45 +0,0 @@
#include "indexer/caching_rank_table_loader.hpp"
#include "search/dummy_rank_table.hpp"
#include "indexer/data_source.hpp"
CachingRankTableLoader::CachingRankTableLoader(DataSource const & dataSource, std::string const & sectionName)
: m_dataSource(dataSource)
, m_sectionName(sectionName)
{}
uint8_t CachingRankTableLoader::Get(FeatureID const & featureId) const
{
auto const handle = m_dataSource.GetMwmHandleById(featureId.m_mwmId);
if (!handle.IsAlive())
return search::RankTable::kNoRank;
auto it = m_deserializers.find(featureId.m_mwmId);
if (it == m_deserializers.end())
{
auto rankTable = search::RankTable::Load(handle.GetValue()->m_cont, m_sectionName);
if (!rankTable)
rankTable = std::make_unique<search::DummyRankTable>();
auto const result = m_deserializers.emplace(featureId.m_mwmId, std::move(rankTable));
it = result.first;
}
return it->second->Get(featureId.m_index);
}
void CachingRankTableLoader::OnMwmDeregistered(platform::LocalCountryFile const & localFile)
{
for (auto it = m_deserializers.begin(); it != m_deserializers.end(); ++it)
{
if (it->first.IsDeregistered(localFile))
{
m_deserializers.erase(it);
return;
}
}
}

View File

@@ -1,32 +0,0 @@
#pragma once
#include "indexer/feature_decl.hpp"
#include "indexer/mwm_set.hpp"
#include "indexer/rank_table.hpp"
#include "base/macros.hpp"
#include <map>
#include <memory>
#include <string>
class DataSource;
struct FeatureID;
// *NOTE* This class IS NOT thread-safe.
class CachingRankTableLoader
{
public:
CachingRankTableLoader(DataSource const & dataSource, std::string const & sectionName);
/// @return 0 if there is no rank for feature.
uint8_t Get(FeatureID const & featureId) const;
void OnMwmDeregistered(platform::LocalCountryFile const & localFile);
private:
DataSource const & m_dataSource;
std::string const m_sectionName;
mutable std::map<MwmSet::MwmId, std::unique_ptr<search::RankTable>> m_deserializers;
DISALLOW_COPY(CachingRankTableLoader);
};

View File

@@ -276,7 +276,6 @@ Framework::Framework(FrameworkParams const & params, bool loadMaps)
, m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1, false /* rough */), kMaxTrafficCacheSizeBytes,
m_routingManager.RoutingSession())
, m_lastReportedCountry(kInvalidCountryId)
, m_popularityLoader(m_featuresFetcher.GetDataSource(), POPULARITY_RANKS_FILE_TAG)
, m_descriptionsLoader(std::make_unique<descriptions::Loader>(m_featuresFetcher.GetDataSource()))
{
// Editor should be initialized from the main thread to set its ThreadChecker.
@@ -445,7 +444,7 @@ void Framework::OnMapDeregistered(platform::LocalCountryFile const & localFile)
m_transitManager.OnMwmDeregistered(localFile);
m_isolinesManager.OnMwmDeregistered(localFile);
m_trafficManager.OnMwmDeregistered(localFile);
m_popularityLoader.OnMwmDeregistered(localFile);
m_descriptionsLoader->OnMwmDeregistered(localFile);
m_storage.DeleteCustomCountryVersion(localFile);
};
@@ -3072,10 +3071,6 @@ osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject em
auto const result = osm::Editor::Instance().SaveEditedFeature(emo);
// Automatically select newly created and edited objects.
if (m_currentPlacePageInfo)
DeactivateMapSelection();
place_page::BuildInfo info;
info.m_mercator = emo.GetMercator();
info.m_featureId = emo.GetID();

View File

@@ -32,7 +32,6 @@
#include "editor/new_feature_categories.hpp"
#include "editor/osm_editor.hpp"
#include "indexer/caching_rank_table_loader.hpp"
#include "indexer/data_source.hpp"
#include "indexer/data_source_helpers.hpp"
#include "indexer/map_object.hpp"
@@ -484,8 +483,6 @@ private:
TrackRecordingUpdateHandler m_trackRecordingUpdateHandler;
CachingRankTableLoader m_popularityLoader;
std::unique_ptr<descriptions::Loader> m_descriptionsLoader;
public:

View File

@@ -1171,6 +1171,7 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
{
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo);
m_gpsInfoCache.reset();
}
@@ -1515,7 +1516,9 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(), routeMatchingInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
routeMatchingInfo);
}
void RoutingManager::DeleteSavedRoutePoints()

View File

@@ -57,5 +57,16 @@ std::string DebugPrint(ScopedDir const & dir)
os << "ScopedDir [" << dir.GetFullPath() << "]";
return os.str();
}
ScopedDirCleanup::ScopedDirCleanup(std::string const & path) : m_fullPath(path)
{
UNUSED_VALUE(Platform::MkDir(m_fullPath));
}
ScopedDirCleanup::~ScopedDirCleanup()
{
UNUSED_VALUE(Platform::RmDirRecursively(m_fullPath));
}
} // namespace tests_support
} // namespace platform

View File

@@ -38,6 +38,15 @@ private:
DISALLOW_COPY_AND_MOVE(ScopedDir);
};
class ScopedDirCleanup
{
std::string const m_fullPath;
public:
explicit ScopedDirCleanup(std::string const & path);
~ScopedDirCleanup();
};
std::string DebugPrint(ScopedDir const & dir);
} // namespace tests_support
} // namespace platform

View File

@@ -363,6 +363,32 @@ void GetFullRoadName(RouteSegment::RoadNameInfo & road, std::string & name)
}
}
double RoutingSession::GetDistanceToNextTurn() const
{
if (!m_route->IsValid())
return -1;
double distanceToTurnMeters = 0.;
turns::TurnItem turn;
m_route->GetNearestTurn(distanceToTurnMeters, turn);
return distanceToTurnMeters;
}
double RoutingSession::GetCurrentSpeedLimit() const
{
if (!m_route->IsValid())
return -1;
SpeedInUnits speedLimit;
m_route->GetCurrentSpeedLimit(speedLimit);
if (speedLimit.IsNumeric())
return measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
return 0;
else
return -1.0;
}
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
@@ -392,14 +418,7 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
info.m_turn = turn.m_turn;
SpeedInUnits speedLimit;
m_route->GetCurrentSpeedLimit(speedLimit);
if (speedLimit.IsNumeric())
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
info.m_speedLimitMps = 0;
else
info.m_speedLimitMps = -1.0;
info.m_speedLimitMps = GetCurrentSpeedLimit();
// The turn after the next one.
if (m_routingSettings.m_showTurnAfterNext)

View File

@@ -100,6 +100,8 @@ public:
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
void GetRouteFollowingInfo(FollowingInfo & info) const;
double GetDistanceToNextTurn() const;
double GetCurrentSpeedLimit() const;
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
void MatchLocationToRoadGraph(location::GpsInfo & location);

View File

@@ -76,7 +76,7 @@ char const * g_strings[] = {
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
// sort | uniq
vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
array<string_view, 48> constexpr g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
@@ -85,13 +85,14 @@ vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L
"NNBNL"};
// List of patterns which look like house numbers more than other patterns. Constructed by hand.
vector<string> const g_patternsStrict = {"N", "NBN", "NBL", "NL"};
array<string_view, 4> constexpr g_patternsStrict = {"N", "NBN", "NBL", "NL"};
// List of common synonyms for building parts. Constructed by hand.
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
// List of common stop words for buildings. Constructed by hand.
// TODO: add more stop words?
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
bool IsStopWord(UniString const & s, bool isPrefix)
@@ -167,7 +168,8 @@ class HouseNumberClassifier
public:
using Patterns = StringSet<Token::Type, 4>;
HouseNumberClassifier(vector<string> const & patterns = g_patterns)
template <size_t size>
HouseNumberClassifier(array<string_view, size> const & patterns)
{
for (auto const & p : patterns)
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
@@ -590,7 +592,7 @@ bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & qu
bool LooksLikeHouseNumber(UniString const & s, bool isPrefix)
{
static HouseNumberClassifier const classifier;
static HouseNumberClassifier const classifier(g_patterns);
return classifier.LooksGood(s, isPrefix);
}

View File

@@ -298,8 +298,7 @@ void LocalityScorer::GetDocVecs(uint32_t localityId, vector<DocVec> & dvs) const
DocVec::Builder builder;
ForEachNormalizedToken(name, [&](strings::UniString const & token)
{
if (!IsStopWord(token))
builder.Add(token);
builder.Add(token);
});
dvs.emplace_back(std::move(builder));
}

View File

@@ -69,21 +69,6 @@ m2::RectD GetRectAroundPosition(m2::PointD const & position)
return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM);
}
// Removes all full-token stop words from |tokens|.
// Does nothing if all tokens are non-prefix stop words.
void RemoveStopWordsIfNeeded(QueryTokens & tokens, strings::UniString & prefix)
{
size_t numStopWords = 0;
for (auto const & token : tokens)
if (IsStopWord(token))
++numStopWords;
if (numStopWords == tokens.size() && prefix.empty())
return;
tokens.erase_if(&IsStopWord);
}
void TrimLeadingSpaces(string & s)
{
while (!s.empty() && strings::IsASCIISpace(s.front()))
@@ -277,9 +262,6 @@ void Processor::SetQuery(string const & query, bool categorialRequest /* = false
}
}
// Remove stopwords *after* FillCategories call (it makes exact tokens match).
RemoveStopWordsIfNeeded(m_query.m_tokens, m_query.m_prefix);
if (!m_isCategorialRequest)
{
// Assign tokens and prefix to scorer.

View File

@@ -1482,13 +1482,7 @@ unordered_map<string, vector<string>> const kSynonyms = {
// QueryParams::Token ------------------------------------------------------------------------------
void QueryParams::Token::AddSynonym(string const & s)
{
AddSynonym(strings::MakeUniString(s));
}
void QueryParams::Token::AddSynonym(String const & s)
{
if (!IsStopWord(s))
m_synonyms.push_back(s);
m_synonyms.push_back(strings::MakeUniString(s));
}
string DebugPrint(QueryParams::Token const & token)
@@ -1510,10 +1504,11 @@ void QueryParams::ClearStreetIndices()
AdditionalCommonTokens()
{
char const * arr[] = {
"the", // English
"der", "zum", "und", "auf", // German
"del", "les", // Spanish
"в", "на" // Cyrillic
"a", "and", "s", "the", // English
"am", "an", "auf", "der", "im", "und", "zum", // German
"d", "da", "de", "del", "di", "du", "el",
"et", "la", "las", "le", "les", "los", "y", // French, Spanish, Italian
"в", "и", "на", "я" // Cyrillic
};
for (char const * s : arr)
m_strings.insert(NormalizeAndSimplifyString(s));

View File

@@ -28,7 +28,6 @@ public:
Token(String const & original) : m_original(original) {}
void AddSynonym(std::string const & s);
void AddSynonym(String const & s);
template <typename Fn>
void ForEachSynonym(Fn && fn) const

View File

@@ -94,42 +94,9 @@ ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniStr
}
} // namespace impl
bool IsStopWord(UniString const & s)
{
/// @todo Get all common used stop words and take out this array into search_string_utils.cpp module for example.
/// Should skip this tokens when building search index?
class StopWordsChecker
{
set<UniString> m_set;
public:
StopWordsChecker()
{
// Don't want to put _full_ stopwords list, not to break current ranking.
// Only 2-letters and the most common.
char const * arr[] = {
"a", "s", "the", // English
"am", "im", "an", // German
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
"и", "я" // Cyrillic
};
for (char const * s : arr)
m_set.insert(MakeUniString(s));
}
bool Has(UniString const & s) const { return m_set.count(s) > 0; }
};
static StopWordsChecker const swChecker;
return swChecker.Has(s);
}
TokensVector::TokensVector(string_view name)
{
ForEachNormalizedToken(name, [this](strings::UniString && token)
{
if (!IsStopWord(token))
m_tokens.push_back(std::move(token));
});
m_tokens = NormalizeAndTokenizeString(std::move(name));
Init();
}

View File

@@ -180,9 +180,6 @@ struct NameScores
std::string DebugPrint(NameScore const & score);
std::string DebugPrint(NameScores const & scores);
// Returns true when |s| is a stop-word and may be removed from a query.
bool IsStopWord(strings::UniString const & s);
class TokensVector
{
std::vector<strings::UniString> m_tokens;

View File

@@ -44,11 +44,7 @@ public:
m_scorer.SetPivotForTesting(pivot);
vector<UniString> tokens;
search::ForEachNormalizedToken(query, [&tokens](strings::UniString && token)
{
if (!IsStopWord(token))
tokens.push_back(std::move(token));
});
tokens = NormalizeAndTokenizeString(query);
m_params.Init(query, tokens, lastTokenIsPrefix);
}

View File

@@ -339,7 +339,8 @@ void MapWidget::ShowInfoPopup(QMouseEvent * e, m2::PointD const & pt)
auto types = feature::TypesHolder(ft);
types.SortBySpec();
for (auto const & type : types.ToObjectNames())
concat += type + " ";
concat = concat + type + " ";
concat = concat + "| " + DebugPrint(ft.GetGeomType());
addStringFn(concat);
// Name

View File

@@ -8,7 +8,6 @@
#include "base/assert.hpp"
#include "base/logging.hpp"
#include <algorithm>
#include <functional>
#include <limits>
@@ -200,7 +199,7 @@ void UpdateDialog::OnItemClick(QTreeWidgetItem * item, int column)
case NodeStatus::Partly: st.DownloadNode(countryId); break;
case NodeStatus::InQueue:
case NodeStatus::Downloading: st.DeleteNode(countryId); break;
case NodeStatus::Downloading: st.CancelDownloadNode(countryId); break;
case NodeStatus::Applying:
// Do nothing.

View File

@@ -46,8 +46,6 @@
394E1E0B22BBB5EB00E4BC75 /* utils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 394E1E0922BBB5EB00E4BC75 /* utils.hpp */; };
39F376C0207D32450058E8E0 /* cities_boundaries_serdes_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39F376BE207D32410058E8E0 /* cities_boundaries_serdes_tests.cpp */; };
39F376C3207D32510058E8E0 /* scale_index_reading_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39F376C1207D324E0058E8E0 /* scale_index_reading_tests.cpp */; };
3D12E3D72111B4BE0015A9A9 /* caching_rank_table_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D12E3D52111B4BD0015A9A9 /* caching_rank_table_loader.cpp */; };
3D12E3D82111B4BE0015A9A9 /* caching_rank_table_loader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D12E3D62111B4BD0015A9A9 /* caching_rank_table_loader.hpp */; };
3D489BC61D3D220F0052AA38 /* editable_map_object_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D489BA71D3D1F8A0052AA38 /* editable_map_object_test.cpp */; };
3D489BC71D3D22150052AA38 /* features_vector_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D489BA81D3D1F8A0052AA38 /* features_vector_test.cpp */; };
3D489BC81D3D22190052AA38 /* string_slice_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D489BA91D3D1F8A0052AA38 /* string_slice_tests.cpp */; };
@@ -271,8 +269,6 @@
394E1E0922BBB5EB00E4BC75 /* utils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = utils.hpp; sourceTree = "<group>"; };
39F376BE207D32410058E8E0 /* cities_boundaries_serdes_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cities_boundaries_serdes_tests.cpp; sourceTree = "<group>"; };
39F376C1207D324E0058E8E0 /* scale_index_reading_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scale_index_reading_tests.cpp; sourceTree = "<group>"; };
3D12E3D52111B4BD0015A9A9 /* caching_rank_table_loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = caching_rank_table_loader.cpp; sourceTree = "<group>"; };
3D12E3D62111B4BD0015A9A9 /* caching_rank_table_loader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = caching_rank_table_loader.hpp; sourceTree = "<group>"; };
3D452AF71EE6D9F5009EAB9B /* wheelchair_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wheelchair_tests.cpp; sourceTree = "<group>"; };
3D452AF81EE6D9F5009EAB9B /* feature_names_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = feature_names_test.cpp; sourceTree = "<group>"; };
3D452AF91EE6D9F5009EAB9B /* centers_table_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = centers_table_test.cpp; sourceTree = "<group>"; };
@@ -609,8 +605,6 @@
34664CEF1D49FEC1003D7096 /* altitude_loader.hpp */,
4088CE1F21AE993F00E2702A /* brands_holder.cpp */,
4088CE1E21AE993F00E2702A /* brands_holder.hpp */,
3D12E3D52111B4BD0015A9A9 /* caching_rank_table_loader.cpp */,
3D12E3D62111B4BD0015A9A9 /* caching_rank_table_loader.hpp */,
56C74C121C749E4700B71B9F /* categories_holder_loader.cpp */,
56C74C131C749E4700B71B9F /* categories_holder.cpp */,
56C74C141C749E4700B71B9F /* categories_holder.hpp */,
@@ -788,7 +782,6 @@
347F337D1C454242009758CC /* succinct_trie_builder.hpp in Headers */,
675341381A3F540F00A0A8C3 /* mwm_set.hpp in Headers */,
456E1B181F90E5B7009C32E1 /* cities_boundaries_serdes.hpp in Headers */,
3D12E3D82111B4BE0015A9A9 /* caching_rank_table_loader.hpp in Headers */,
670EE56D1B60033A001E8064 /* unique_index.hpp in Headers */,
675340FF1A3F540F00A0A8C3 /* cell_coverer.hpp in Headers */,
56C74C251C749E4700B71B9F /* search_string_utils.hpp in Headers */,
@@ -1001,7 +994,6 @@
6753410D1A3F540F00A0A8C3 /* drawing_rules.cpp in Sources */,
675341301A3F540F00A0A8C3 /* data_source.cpp in Sources */,
34664CF61D49FEC1003D7096 /* centers_table.cpp in Sources */,
3D12E3D72111B4BE0015A9A9 /* caching_rank_table_loader.cpp in Sources */,
6753414D1A3F540F00A0A8C3 /* types_mapping.cpp in Sources */,
34583BC71C88552100F94664 /* cuisines.cpp in Sources */,
675341121A3F540F00A0A8C3 /* feature_algo.cpp in Sources */,

View File

@@ -50,8 +50,6 @@
671ED38F20D403B300D4317E /* search_api_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 671ED38A20D403B300D4317E /* search_api_tests.cpp */; };
674A29F01B26FD6F001A525C /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 674A29EE1B26FD5F001A525C /* testingmain.cpp */; };
674A2A2F1B26FF7B001A525C /* libmap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 675345BB1A4054AD00A0A8C3 /* libmap.a */; };
674A2A361B27011A001A525C /* working_time_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 674A2A351B27011A001A525C /* working_time_tests.cpp */; };
674A2A381B2715FB001A525C /* osm_opening_hours.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 674A2A371B2715FB001A525C /* osm_opening_hours.hpp */; };
674C38621BFF3095000D603B /* user_mark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 674C385F1BFF3095000D603B /* user_mark.cpp */; };
675346481A4054E800A0A8C3 /* bookmark_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 675345D91A4054E800A0A8C3 /* bookmark_manager.cpp */; };
675346491A4054E800A0A8C3 /* bookmark_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 675345DA1A4054E800A0A8C3 /* bookmark_manager.hpp */; };
@@ -202,8 +200,6 @@
674A29CF1B26FCFE001A525C /* mwm_url_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mwm_url_tests.cpp; sourceTree = "<group>"; };
674A29DF1B26FD1C001A525C /* map_tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = map_tests.app; sourceTree = BUILT_PRODUCTS_DIR; };
674A29EE1B26FD5F001A525C /* testingmain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testingmain.cpp; path = ../../../libs/testing/testingmain.cpp; sourceTree = "<group>"; };
674A2A351B27011A001A525C /* working_time_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = working_time_tests.cpp; sourceTree = "<group>"; };
674A2A371B2715FB001A525C /* osm_opening_hours.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = osm_opening_hours.hpp; sourceTree = "<group>"; };
674C385F1BFF3095000D603B /* user_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_mark.cpp; sourceTree = "<group>"; };
675345BB1A4054AD00A0A8C3 /* libmap.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmap.a; sourceTree = BUILT_PRODUCTS_DIR; };
675345D91A4054E800A0A8C3 /* bookmark_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bookmark_manager.cpp; sourceTree = "<group>"; };
@@ -357,7 +353,6 @@
671ED38A20D403B300D4317E /* search_api_tests.cpp */,
674A29EE1B26FD5F001A525C /* testingmain.cpp */,
BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */,
674A2A351B27011A001A525C /* working_time_tests.cpp */,
ED49D74B2CEF3CE3004AF27E /* elevation_info_tests.cpp */,
ED85D1CF2D5F508700D8075D /* track_statistics_tests.cpp */,
);
@@ -432,7 +427,6 @@
45F6EE9B1FB1C77500019892 /* mwm_tree.hpp */,
675346051A4054E800A0A8C3 /* mwm_url.cpp */,
675346061A4054E800A0A8C3 /* mwm_url.hpp */,
674A2A371B2715FB001A525C /* osm_opening_hours.hpp */,
34583BCD1C88556800F94664 /* place_page_info.cpp */,
34583BCE1C88556800F94664 /* place_page_info.hpp */,
3DF528D5237DC82E000ED0D5 /* position_provider.hpp */,
@@ -519,7 +513,6 @@
6753469C1A4054E800A0A8C3 /* track.hpp in Headers */,
675346651A4054E800A0A8C3 /* framework.hpp in Headers */,
BBA014B120754997007402E4 /* user_mark_id_storage.hpp in Headers */,
674A2A381B2715FB001A525C /* osm_opening_hours.hpp in Headers */,
ED85D1CC2D5F4B5B00D8075D /* track_statistics.hpp in Headers */,
3DEE1ADF21EE03B400054A91 /* power_manager.hpp in Headers */,
F6D2CE7F1EDEB7F500636DFD /* routing_manager.hpp in Headers */,
@@ -671,7 +664,6 @@
FAA8387426BB3C0F002E54C6 /* countries_names_tests.cpp in Sources */,
679624B01D1017DB00AE4E3C /* gps_track_storage_test.cpp in Sources */,
674A29F01B26FD6F001A525C /* testingmain.cpp in Sources */,
674A2A361B27011A001A525C /* working_time_tests.cpp in Sources */,
679624B11D1017DB00AE4E3C /* gps_track_test.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;