From 71aaed860b092f2ca8da48ff1eb50c71ac57b68d Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 14 Jan 2024 16:47:10 +0000 Subject: [PATCH 01/14] Codechange: Missing some conversions to WidgetID. (#11773) --- src/build_vehicle_gui.cpp | 2 +- src/engine_gui.h | 2 +- src/help_gui.cpp | 2 +- src/osk_gui.cpp | 2 +- src/window_gui.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 0427125399..d71763ff00 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1095,7 +1095,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li * @param selected Currently selected sort criterium. * @param button Widget button. */ -void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button) +void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, WidgetID button) { uint32_t hidden_mask = 0; /* Disable sorting by power or tractive effort when the original acceleration model for road vehicles is being used. */ diff --git a/src/engine_gui.h b/src/engine_gui.h index 21e09b0f9d..c6a20cb327 100644 --- a/src/engine_gui.h +++ b/src/engine_gui.h @@ -51,6 +51,6 @@ extern const StringID _engine_sort_listing[][12]; extern EngList_SortTypeFunction * const _engine_sort_functions[][11]; uint GetEngineListHeight(VehicleType type); -void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button); +void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, WidgetID button); #endif /* ENGINE_GUI_H */ diff --git a/src/help_gui.cpp b/src/help_gui.cpp index 60fde1db92..3c34b0fb0a 100644 --- a/src/help_gui.cpp +++ b/src/help_gui.cpp @@ -160,7 +160,7 @@ struct HelpWindow : public Window { } private: - void EnableTextfileButton(std::string_view filename, int button_widget) + void EnableTextfileButton(std::string_view filename, WidgetID button_widget) { this->GetWidget(button_widget)->SetDisabled(!FindGameManualFilePath(filename).has_value()); } diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index bdd1e0f0e3..bb3d49bf6a 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -42,7 +42,7 @@ struct OskWindow : public Window { std::string orig_str; ///< Original string. bool shift; ///< Is the shift effectively pressed? - OskWindow(WindowDesc *desc, Window *parent, int button) : Window(desc) + OskWindow(WindowDesc *desc, Window *parent, WidgetID button) : Window(desc) { this->parent = parent; assert(parent != nullptr); diff --git a/src/window_gui.h b/src/window_gui.h index 1243239c6a..3464af8a51 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -258,7 +258,7 @@ public: ViewportData *viewport; ///< Pointer to viewport data, if present. const NWidgetCore *nested_focus; ///< Currently focused nested widget, or \c nullptr if no nested widget has focus. - std::map querystrings; ///< QueryString associated to WWT_EDITBOX widgets. + std::map querystrings; ///< QueryString associated to WWT_EDITBOX widgets. std::unique_ptr nested_root; ///< Root of the nested tree. WidgetLookup widget_lookup; ///< Indexed access to the nested widget tree. Do not access directly, use #Window::GetWidget() instead. NWidgetStacked *shade_select; ///< Selection widget (#NWID_SELECTION) to use for shading the window. If \c nullptr, window cannot shade. From f219557cf233fdc69f10afa5ad18501b3884c63e Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 14 Jan 2024 18:12:40 +0000 Subject: [PATCH 02/14] Codechange: List functions in gui.h under correct source file. (#11775) --- src/gui.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/gui.h b/src/gui.h index cbdeafc4c1..772a53ddb0 100644 --- a/src/gui.h +++ b/src/gui.h @@ -43,25 +43,38 @@ void ShowHeightmapLoad(); /* misc_gui.cpp */ void ShowLandInfo(TileIndex tile); void ShowAboutWindow(); +void ShowEstimatedCostOrIncome(Money cost, int x, int y); + +/* tree_gui.cpp */ void ShowBuildTreesToolbar(); + +/* town_gui.cpp */ void ShowTownDirectory(); +void ShowFoundTownWindow(); + +/* industry_gui.cpp */ void ShowIndustryDirectory(); void ShowIndustryCargoesWindow(); +void ShowBuildIndustryWindow(); + +/* subsidy_gui.cpp */ void ShowSubsidiesList(); + +/* goal_gui.cpp */ void ShowGoalsList(CompanyID company); void ShowGoalQuestion(uint16_t id, byte type, uint32_t button_mask, const std::string &question); -void ShowStoryBook(CompanyID company, uint16_t page_id = INVALID_STORY_PAGE); -void ShowEstimatedCostOrIncome(Money cost, int x, int y); +/* story_gui.cpp */ +void ShowStoryBook(CompanyID company, uint16_t page_id = INVALID_STORY_PAGE); +/* viewport_gui.cpp */ void ShowExtraViewportWindow(TileIndex tile = INVALID_TILE); void ShowExtraViewportWindowForTileUnderCursor(); /* bridge_gui.cpp */ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type); -void ShowBuildIndustryWindow(); -void ShowFoundTownWindow(); +/* music_gui.cpp */ void ShowMusicWindow(); #endif /* GUI_H */ From e8d6b496c201482dbaaecaeff7d760ec4d7ee70f Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 14 Jan 2024 18:39:10 +0000 Subject: [PATCH 03/14] Update: Translations from eints english (au): 1 change by krysclarke english (us): 1 change by 2TallTyler chinese (simplified): 9 changes by WenSimEHRP korean: 1 change by telk5093 russian: 1 change by Ln-Wolf finnish: 1 change by hpiirai danish: 2 changes by bscargo french: 2 changes by ottdfevr portuguese: 1 change by azulcosta --- src/lang/danish.txt | 3 ++- src/lang/english_AU.txt | 2 +- src/lang/english_US.txt | 2 +- src/lang/finnish.txt | 2 +- src/lang/french.txt | 4 ++-- src/lang/korean.txt | 2 +- src/lang/portuguese.txt | 2 +- src/lang/russian.txt | 2 +- src/lang/simplified_chinese.txt | 18 +++++++++--------- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 01f78b0cd7..3a76f963b6 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -1002,6 +1002,7 @@ STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kong Dolla STR_GAME_OPTIONS_CURRENCY_INR :Indisk rupi STR_GAME_OPTIONS_CURRENCY_IDR :Indonesisk Rupiah STR_GAME_OPTIONS_CURRENCY_MYR :Malaysisk Ringgit +STR_GAME_OPTIONS_CURRENCY_LVL :lettiske lats STR_GAME_OPTIONS_AUTOSAVE_FRAME :{BLACK}Automatisk gemning STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :{BLACK}Vælg interval imellem automatisk gemning @@ -3016,7 +3017,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Ejer af STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Lokal myndighed: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Ingen STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Koordinater: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Produceret: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Bygget/renoveret: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Stationsklasse: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Stationstype: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Lufthavnsklasse: {LTBLUE}{STRING} diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index ceeec96b0c..32db2da2c0 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -3017,7 +3017,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Railway STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Local authority: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :None STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Built: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Built/renovated: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Station class: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Station type: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Airport class: {LTBLUE}{STRING} diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 74201473de..d95cdb1a76 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -3017,7 +3017,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Railroad STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Local authority: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :None STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Co-ordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Built: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Built/renovated: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Station class: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Station type: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Airport class: {LTBLUE}{STRING} diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index e89aed2e72..a5065187e3 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -3017,7 +3017,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Rautatie STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Kunta: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Ei mitään STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Koordinaatit: {LTBLUE}{NUM}×{NUM}×{NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Rakennettu: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Rakennettu/peruskorjattu: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Aseman luokka: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Aseman tyyppi: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Lentokentän luokka: {LTBLUE}{STRING} diff --git a/src/lang/french.txt b/src/lang/french.txt index 886770b6e0..30bca63088 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -1003,7 +1003,7 @@ STR_GAME_OPTIONS_CURRENCY_HKD :Dollar de Hong STR_GAME_OPTIONS_CURRENCY_INR :Roupie indienne STR_GAME_OPTIONS_CURRENCY_IDR :Roupie indonésienne STR_GAME_OPTIONS_CURRENCY_MYR :Malaysian Ringgit -STR_GAME_OPTIONS_CURRENCY_LVL :Lats +STR_GAME_OPTIONS_CURRENCY_LVL :Lats letton STR_GAME_OPTIONS_AUTOSAVE_FRAME :{BLACK}Sauvegarde automatique STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :{BLACK}Sélectionner l'intervalle de temps entre les sauvegardes automatiques @@ -3018,7 +3018,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Proprié STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Municipalité{NBSP}: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Aucune STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Coordonnées{NBSP}: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Construit le{NBSP}: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Construit/rénové le{NBSP}: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Type de station{NBSP}: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Type de station{NBSP}: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Type d'aéroport{NBSP}: {LTBLUE}{STRING} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 15ea9fc14f..9ad076ad09 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2727,7 +2727,7 @@ STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}자동 STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}차량기지를 건설합니다. 차량을 구입하거나 점검을 할 수 있습니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}선로에 경유지를 설치합니다. CTRL 키를 사용하면 같은 이름의 경유지를 서로 떨어진 곳에 지을 수 있습니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}철도역을 짓습니다. CTRL 키를 사용하면 같은 이름의 역을 서로 떨어진 곳에 지을 수 있습니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}신호기를 설치합니다. CTRL 키를 누르면 구식/전자식으로 전환합니다.{}선로를 따라 드래그해서 설치할 수 있습니다. CTRL 키를 누른 채로 드래그하면 다음 분기점이나 다음 신호기까지 신호기를 설치합니다.{}CTRL 키를 누른 채 클릭하면 신호기 선택 창을 전환합니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}선로에 신호기를 설치합니다. CTRL 키를 누르면 구식/전자식으로 전환합니다.{}선로를 따라 드래그해서 설치할 수 있습니다. CTRL 키를 누른 채로 드래그하면 다음 분기점이나 다음 신호기까지 신호기를 설치합니다.{}CTRL 키를 누른 채 클릭하면 신호기 선택 창을 전환합니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}철교를 짓습니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}터널을 짓습니다. SHIFT 키를 누른 채로 사용하면 예상 비용을 볼 수 있습니다 STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}선로, 신호기, 경유지, 역 등의 철도 시설 건설/철거 모드를 켜거나 끌 수 있습니다. CTRL 키를 누르고 있어도 선로에서 경유지와 역을 제거할 수 있습니다 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index b8f669a30c..fc91c0bbcc 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -3018,7 +3018,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Dono da STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Autoridade local: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Nenhum STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Construído: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Construído/renovado: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Tipo de estação: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Tipo de estação: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Tipo de aeroporto: {LTBLUE}{STRING} diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 93e988d6dd..51be414a6c 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -3192,7 +3192,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Влад STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Администрация: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Нет STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Координаты: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Построено: {LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Построено/обновлено: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Класс станции: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Тип станции: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Класс аэропорта: {LTBLUE}{STRING.nom} diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index f4eb7d732b..1b98880ebc 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -350,7 +350,7 @@ STR_SORT_BY_CARGO_CAPACITY :运载能力 STR_SORT_BY_RANGE :航行距离 STR_SORT_BY_POPULATION :人口 STR_SORT_BY_RATING :评价 -STR_SORT_BY_NUM_VEHICLES :交通工具数量 +STR_SORT_BY_NUM_VEHICLES :载具数量 STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :去年总利润 STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :今年总利润 STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :去年平均利润 @@ -1325,7 +1325,7 @@ STR_CONFIG_SETTING_PERCENTAGE :{COMMA}% STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS :汽车斜坡坡度: {STRING} STR_CONFIG_SETTING_ROAD_VEHICLE_SLOPE_STEEPNESS_HELPTEXT :设置对汽车而言,一格斜坡的坡度大小。数值越高,坡度越大,汽车越难爬上斜坡。 -STR_CONFIG_SETTING_FORBID_90_DEG :禁止列车 90 度转弯:{STRING} +STR_CONFIG_SETTING_FORBID_90_DEG :禁止列车直角转向:{STRING} STR_CONFIG_SETTING_FORBID_90_DEG_HELPTEXT :当水平方向轨道与垂直方向轨道交叉时,没有采用45度的轨道组合连接,而是采用轨道90度直接连接时,列车通过时需要90度转弯,当本设置”打开“时,将禁止火车90度转弯。 STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS :允许非毗邻站台合并:{STRING} @@ -1344,7 +1344,7 @@ STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH :隧道最大长 STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH_HELPTEXT :建设隧道时允许的最大长度 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD :原料工业建设方式: {STRING} -STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :建立重工业企业的的设定. '禁止'表示不能建立; '勘探'表示可以建立但是只能在地图上一随机处, 并可能会失败; '像别的工业一样'表示采矿业也能像其它加工业那样可以随意在任何地方建立. +STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :设定原料工业的建造方式。“禁止”表示不能建造;“勘探”表示可以建立但是只能在地图上一随机处,并可能会失败;“同其他工业”表示可以和随意建造。 ###length 3 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE :不允许 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL :同其他工业 @@ -1911,7 +1911,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :四倍(原版 STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :线性 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :树木自动生长: {STRING} -STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :控制游戏中数目的随机生长,这将影响依赖树木的工业,比如木材厂 +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :控制游戏内树木的生长。此选项可能会影响一些依赖树木的工业,例如伐木场。 ###length 4 STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :生长但不扩散 {RED}(损坏伐木场) STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :仅在雨林扩散 @@ -2826,7 +2826,7 @@ STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}建设/ STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}转换/升级 公路类型。按住 Shift 键显示预计费用。 STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :转换/升级 电车道类型。按住 Shift 键显示预计费用。 -STR_ROAD_NAME_ROAD :路 +STR_ROAD_NAME_ROAD :公路 STR_ROAD_NAME_TRAM :电车轨道 # Road depot construction window @@ -3017,7 +3017,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}铁路 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}地方政府:{LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :没有 STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}坐标: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING}) -STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}建造时间:{LTBLUE}{DATE_LONG} +STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}建造/翻新于:{LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}车站分类: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}车站类型: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}飞机场分类: {LTBLUE}{STRING} @@ -3246,7 +3246,7 @@ STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形特点: STR_MAPGEN_SEA_LEVEL :{BLACK}海洋面积: STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}选择海洋覆盖率 -STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}河流数量: +STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}河流数量: STR_MAPGEN_SMOOTHNESS :{BLACK}平滑程度: STR_MAPGEN_VARIETY :{BLACK}多样地形: STR_MAPGEN_GENERATE :{WHITE}生成 @@ -3854,7 +3854,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}运河 STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}站台: STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS :{WHITE}车站 STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS :{WHITE}机场 -STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}每年{CURRENCY_LONG} +STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENCY_LONG}/年 # Industry directory STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}工业设施 @@ -5625,7 +5625,7 @@ STR_VEHICLE_NAME_AIRCRAFT_POWERNAUT_HELICOPTER :Powernaut 直 # Formatting of some strings STR_FORMAT_DATE_TINY :{ZEROFILL_NUM}-{ZEROFILL_NUM}-{NUM} STR_FORMAT_DATE_SHORT :{STRING} {NUM} -STR_FORMAT_DATE_LONG :{2:NUM}年 {1:STRING}月 {0:STRING}日 +STR_FORMAT_DATE_LONG :{2:NUM} 年 {1:STRING} 月 {0:STRING} 日 STR_FORMAT_DATE_ISO :{2:NUM}-{1:ZEROFILL_NUM}-{0:ZEROFILL_NUM} STR_FORMAT_COMPANY_NUM :(公司 {COMMA}) From a6873ef7dd1da93f0d954817d7b68a1621b4a04c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 14 Jan 2024 19:06:50 +0000 Subject: [PATCH 04/14] Codechange: Avoid repeatedly calling virtual methods in text drawing loop. (#11774) --- src/gfx.cpp | 10 ++++++---- src/gfx_layout.cpp | 17 +++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 6912e4abf5..64b10844b8 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -579,6 +579,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, bool draw_shadow = false; for (int run_index = 0; run_index < line.CountRuns(); run_index++) { const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index); + const auto &glyphs = run.GetGlyphs(); + const auto &positions = run.GetPositions(); const Font *f = run.GetFont(); FontCache *fc = f->fc; @@ -592,14 +594,14 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, draw_shadow = fc->GetDrawGlyphShadow() && (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK; for (int i = 0; i < run.GetGlyphCount(); i++) { - GlyphID glyph = run.GetGlyphs()[i]; + GlyphID glyph = glyphs[i]; /* Not a valid glyph (empty) */ if (glyph == 0xFFFF) continue; - int begin_x = (int)run.GetPositions()[i * 2] + left - offset_x; - int end_x = (int)run.GetPositions()[i * 2 + 2] + left - offset_x - 1; - int top = (int)run.GetPositions()[i * 2 + 1] + y; + int begin_x = (int)positions[i * 2] + left - offset_x; + int end_x = (int)positions[i * 2 + 2] + left - offset_x - 1; + int top = (int)positions[i * 2 + 1] + y; /* Truncated away. */ if (truncation && (begin_x < min_x || end_x > max_x)) continue; diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 2f479247ec..13ca5902d9 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -254,11 +254,13 @@ Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const /* Scan all runs until we've found our code point index. */ for (int run_index = 0; run_index < line->CountRuns(); run_index++) { const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); + const auto &positions = run.GetPositions(); + const auto &charmap = run.GetGlyphToCharMap(); for (int i = 0; i < run.GetGlyphCount(); i++) { /* Matching glyph? Return position. */ - if ((size_t)run.GetGlyphToCharMap()[i] == index) { - Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] }; + if ((size_t)charmap[i] == index) { + Point p = { (int)positions[i * 2], (int)positions[i * 2 + 1] }; return p; } } @@ -281,17 +283,20 @@ ptrdiff_t Layouter::GetCharAtPosition(int x, size_t line_index) const for (int run_index = 0; run_index < line->CountRuns(); run_index++) { const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index); + const auto &glyphs = run.GetGlyphs(); + const auto &positions = run.GetPositions(); + const auto &charmap = run.GetGlyphToCharMap(); for (int i = 0; i < run.GetGlyphCount(); i++) { /* Not a valid glyph (empty). */ - if (run.GetGlyphs()[i] == 0xFFFF) continue; + if (glyphs[i] == 0xFFFF) continue; - int begin_x = (int)run.GetPositions()[i * 2]; - int end_x = (int)run.GetPositions()[i * 2 + 2]; + int begin_x = (int)positions[i * 2]; + int end_x = (int)positions[i * 2 + 2]; if (IsInsideMM(x, begin_x, end_x)) { /* Found our glyph, now convert to UTF-8 string index. */ - size_t index = run.GetGlyphToCharMap()[i]; + size_t index = charmap[i]; size_t cur_idx = 0; for (auto str = this->string.begin(); str != this->string.end();) { From 564441e822b3a9ef28fc160a7c3f4797b9e75ec3 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Sun, 14 Jan 2024 21:07:35 +0100 Subject: [PATCH 05/14] Remove: Debug redirect over network It does not work for dedicated servers because upon starting the process to resolve the address to redirect to gets killed. Also with all the async going on in the network code, the debug redirection will start very late in the process. --- docs/openttd.6 | 4 ---- src/debug.cpp | 13 ------------- src/network/core/config.h | 1 - src/network/network.cpp | 26 -------------------------- src/network/network_func.h | 1 - src/openttd.cpp | 10 ---------- 6 files changed, 55 deletions(-) diff --git a/docs/openttd.6 b/docs/openttd.6 index f45021503b..c1cbd88791 100644 --- a/docs/openttd.6 +++ b/docs/openttd.6 @@ -16,7 +16,6 @@ .Op Fl g Op Ar savegame .Op Fl G Ar seed .Op Fl I Ar graphicsset -.Op Fl l Ar host Ns Op : Ns Ar port .Op Fl m Ar driver .Op Fl M Ar musicset .Op Fl n Ar host Ns Oo : Ns Ar port Oc Ns Op # Ns Ar company @@ -82,9 +81,6 @@ Select the graphics set see .Fl h for a full list. -.It Fl l Ar host Ns Op : Ns Ar port -Redirect debug output; see -.Fl d . .It Fl m Ar driver Select the music driver .Ar driver ; diff --git a/src/debug.cpp b/src/debug.cpp index 46d6495324..de70791808 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -22,7 +22,6 @@ #include "3rdparty/fmt/chrono.h" #include "network/network_admin.h" -SOCKET _debug_socket = INVALID_SOCKET; #include "safeguards.h" @@ -111,18 +110,6 @@ void DumpDebugFacilityNames(std::back_insert_iterator &output_itera */ void DebugPrint(const char *level, const std::string &message) { - if (_debug_socket != INVALID_SOCKET) { - std::string msg = fmt::format("{}dbg: [{}] {}\n", GetLogPrefix(), level, message); - - /* Prevent sending a message concurrently, as that might cause interleaved messages. */ - static std::mutex _debug_socket_mutex; - std::lock_guard lock(_debug_socket_mutex); - - /* Sending out an error when this fails would be nice, however... the error - * would have to be send over this failing socket which won't work. */ - send(_debug_socket, msg.c_str(), (int)msg.size(), 0); - return; - } if (strcmp(level, "desync") == 0) { static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR); if (f == nullptr) return; diff --git a/src/network/core/config.h b/src/network/core/config.h index e6b4882e2b..cbe10ff589 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -24,7 +24,6 @@ static const uint16_t NETWORK_TURN_SERVER_PORT = 3974; ///< The static const uint16_t NETWORK_CONTENT_SERVER_PORT = 3978; ///< The default port of the content server (TCP) static const uint16_t NETWORK_DEFAULT_PORT = 3979; ///< The default port of the game server (TCP & UDP) static const uint16_t NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network -static const uint16_t NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP) static const uint16_t UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet diff --git a/src/network/network.cpp b/src/network/network.cpp index 0914d476f2..66fc844e64 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1218,32 +1218,6 @@ static void NetworkGenerateServerId() _settings_client.network.network_id = GenerateUid("OpenTTD Server ID"); } -class TCPNetworkDebugConnecter : TCPConnecter { -private: - std::string connection_string; - -public: - TCPNetworkDebugConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_DEFAULT_DEBUGLOG_PORT), connection_string(connection_string) {} - - void OnFailure() override - { - Debug(net, 0, "Failed to open connection to {} for redirecting Debug()", this->connection_string); - } - - void OnConnect(SOCKET s) override - { - Debug(net, 3, "Redirecting Debug() to {}", this->connection_string); - - extern SOCKET _debug_socket; - _debug_socket = s; - } -}; - -void NetworkStartDebugLog(const std::string &connection_string) -{ - new TCPNetworkDebugConnecter(connection_string); -} - /** This tries to launch the network for a given OS */ void NetworkStartUp() { diff --git a/src/network/network_func.h b/src/network/network_func.h index 0c0e6d2201..369eb0fc30 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -47,7 +47,6 @@ void NetworkDisconnect(bool close_admins = true); void NetworkGameLoop(); void NetworkBackgroundLoop(); std::string_view ParseFullConnectionString(const std::string &connection_string, uint16_t &port, CompanyID *company_id = nullptr); -void NetworkStartDebugLog(const std::string &connection_string); void NetworkPopulateCompanyStats(NetworkCompanyStats *stats); void NetworkUpdateClientInfo(ClientID client_id); diff --git a/src/openttd.cpp b/src/openttd.cpp index c507abae78..6f4c35845f 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -169,7 +169,6 @@ static void ShowHelp() " -p password = Password to join server\n" " -P password = Password to join company\n" " -D [host][:port] = Start dedicated server\n" - " -l host[:port] = Redirect Debug()\n" #if !defined(_WIN32) " -f = Fork into the background (dedicated only)\n" #endif @@ -489,7 +488,6 @@ static const OptionData _options[] = { GETOPT_SHORT_VALUE('b'), GETOPT_SHORT_OPTVAL('D'), GETOPT_SHORT_VALUE('n'), - GETOPT_SHORT_VALUE('l'), GETOPT_SHORT_VALUE('p'), GETOPT_SHORT_VALUE('P'), #if !defined(_WIN32) @@ -528,7 +526,6 @@ int openttd_main(int argc, char *argv[]) Dimension resolution = {0, 0}; std::unique_ptr scanner(new AfterNewGRFScan()); bool dedicated = false; - char *debuglog_conn = nullptr; bool only_local_path = false; extern bool _dedicated_forks; @@ -565,9 +562,6 @@ int openttd_main(int argc, char *argv[]) case 'n': scanner->connection_string = mgo.opt; // host:port#company parameter break; - case 'l': - debuglog_conn = mgo.opt; - break; case 'p': scanner->join_server_password = mgo.opt; break; @@ -762,10 +756,6 @@ int openttd_main(int argc, char *argv[]) NetworkStartUp(); // initialize network-core - if (debuglog_conn != nullptr && _network_available) { - NetworkStartDebugLog(debuglog_conn); - } - if (!HandleBootstrap()) { ShutdownGame(); return ret; From 37610af0e4a82c33e89dfee58613a5a138aa438b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 14 Jan 2024 22:49:42 +0100 Subject: [PATCH 06/14] Fix: Don't replace stripped characters with '?' in console (#11777) --- src/console.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/console.cpp b/src/console.cpp index 50fc1becba..becbcd644f 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -106,7 +106,7 @@ void IConsolePrint(TextColour colour_code, const std::string &string) /* Create a copy of the string, strip it of colours and invalid * characters and (when applicable) assign it to the console buffer */ - std::string str = StrMakeValid(string); + std::string str = StrMakeValid(string, SVS_NONE); if (_network_dedicated) { NetworkAdminConsole("console", str); From 6e766a2e81ed63ba52650e85a02238ef7b07a27b Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Dec 2023 00:06:19 +0100 Subject: [PATCH 07/14] Change: Allow TrueType fonts to provide our private-use glyphs. --- src/fontcache.h | 3 ++- src/fontcache/freetypefontcache.cpp | 10 ++++++---- src/fontcache/spritefontcache.h | 2 +- src/gfx_layout_icu.cpp | 2 +- src/os/macosx/font_osx.cpp | 10 +++++----- src/os/macosx/font_osx.h | 2 +- src/os/macosx/string_osx.cpp | 6 +++--- src/os/windows/font_win32.cpp | 9 +++------ src/os/windows/font_win32.h | 2 +- src/os/windows/string_uniscribe.cpp | 8 +++++--- src/tests/mock_fontcache.h | 2 +- 11 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/fontcache.h b/src/fontcache.h index 3123c8f59f..73963011b5 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -108,9 +108,10 @@ public: /** * Map a character into a glyph. * @param key The character. + * @param fallback Allow fallback to the parent font. * @return The glyph ID used to draw the character. */ - virtual GlyphID MapCharToGlyph(char32_t key) = 0; + virtual GlyphID MapCharToGlyph(char32_t key, bool fallback = true) = 0; /** * Read a font table from the font. diff --git a/src/fontcache/freetypefontcache.cpp b/src/fontcache/freetypefontcache.cpp index 3e6ddd0f80..eca647d9c8 100644 --- a/src/fontcache/freetypefontcache.cpp +++ b/src/fontcache/freetypefontcache.cpp @@ -41,7 +41,7 @@ public: FreeTypeFontCache(FontSize fs, FT_Face face, int pixels); ~FreeTypeFontCache(); void ClearFontCache() override; - GlyphID MapCharToGlyph(char32_t key) override; + GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override; std::string GetFontName() override { return fmt::format("{}, {}", face->family_name, face->style_name); } bool IsBuiltInFont() override { return false; } const void *GetOSHandle() override { return &face; } @@ -276,15 +276,17 @@ const Sprite *FreeTypeFontCache::InternalGetGlyph(GlyphID key, bool aa) } -GlyphID FreeTypeFontCache::MapCharToGlyph(char32_t key) +GlyphID FreeTypeFontCache::MapCharToGlyph(char32_t key, bool allow_fallback) { assert(IsPrintable(key)); - if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { + FT_UInt glyph = FT_Get_Char_Index(this->face, key); + + if (glyph == 0 && allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { return this->parent->MapCharToGlyph(key); } - return FT_Get_Char_Index(this->face, key); + return glyph; } const void *FreeTypeFontCache::InternalGetFontTable(uint32_t tag, size_t &length) diff --git a/src/fontcache/spritefontcache.h b/src/fontcache/spritefontcache.h index 628a6d08e1..e35cb1a5d6 100644 --- a/src/fontcache/spritefontcache.h +++ b/src/fontcache/spritefontcache.h @@ -29,7 +29,7 @@ public: const Sprite *GetGlyph(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override; bool GetDrawGlyphShadow() override; - GlyphID MapCharToGlyph(char32_t key) override { assert(IsPrintable(key)); return SPRITE_GLYPH | key; } + GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { assert(IsPrintable(key)); return SPRITE_GLYPH | key; } const void *GetFontTable(uint32_t, size_t &length) override { length = 0; return nullptr; } std::string GetFontName() override { return "sprite"; } bool IsBuiltInFont() override { return true; } diff --git a/src/gfx_layout_icu.cpp b/src/gfx_layout_icu.cpp index 83dbf2584d..9cd0fbcdc1 100644 --- a/src/gfx_layout_icu.cpp +++ b/src/gfx_layout_icu.cpp @@ -193,7 +193,7 @@ void ICURun::Shape(UChar *buff, size_t buff_length) for (unsigned int i = 0; i < glyph_count; i++) { int x_advance; - if (buff[glyph_info[i].cluster] >= SCC_SPRITE_START && buff[glyph_info[i].cluster] <= SCC_SPRITE_END) { + if (buff[glyph_info[i].cluster] >= SCC_SPRITE_START && buff[glyph_info[i].cluster] <= SCC_SPRITE_END && glyph_info[i].codepoint == 0) { auto glyph = this->font->fc->MapCharToGlyph(buff[glyph_info[i].cluster]); this->glyphs.push_back(glyph); diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index a41af5a26f..d76fb0ef5c 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -180,14 +180,10 @@ void CoreTextFontCache::SetFontSize(int pixels) Debug(fontcache, 2, "Loaded font '{}' with size {}", this->font_name, pixels); } -GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key) +GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key, bool allow_fallback) { assert(IsPrintable(key)); - if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { - return this->parent->MapCharToGlyph(key); - } - /* Convert characters outside of the Basic Multilingual Plane into surrogate pairs. */ UniChar chars[2]; if (key >= 0x010000U) { @@ -202,6 +198,10 @@ GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key) return glyph[0]; } + if (allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { + return this->parent->MapCharToGlyph(key); + } + return 0; } diff --git a/src/os/macosx/font_osx.h b/src/os/macosx/font_osx.h index ae1cb8feda..56d488771a 100644 --- a/src/os/macosx/font_osx.h +++ b/src/os/macosx/font_osx.h @@ -29,7 +29,7 @@ public: ~CoreTextFontCache() {} void ClearFontCache() override; - GlyphID MapCharToGlyph(char32_t key) override; + GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override; std::string GetFontName() override { return font_name; } bool IsBuiltInFont() override { return false; } const void *GetOSHandle() override { return font.get(); } diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 068767b6fd..3c96bababb 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -189,9 +189,9 @@ static CTRunDelegateCallbacks _sprite_font_callback = { CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color); CGColorRelease(color); - /* Install a size callback for our special sprite glyphs. */ + /* Install a size callback for our special private-use sprite glyphs in case the font does not provide them. */ for (ssize_t c = last; c < i.first; c++) { - if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END) { + if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END && i.second->fc->MapCharToGlyph(buff[c], false) == 0) { CFAutoRelease del(CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24)))); CFAttributedStringSetAttribute(str.get(), CFRangeMake(c, 1), kCTRunDelegateAttributeName, del.get()); } @@ -242,7 +242,7 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font CGGlyph gl[this->glyphs.size()]; CTRunGetGlyphs(run, CFRangeMake(0, 0), gl); for (size_t i = 0; i < this->glyphs.size(); i++) { - if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END) { + if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && gl[i] == 0) { this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]); this->positions[i * 2 + 0] = pts[i].x; this->positions[i * 2 + 1] = (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2; // Align sprite font to centre diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index a05b2211a6..3602c11876 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -282,14 +282,10 @@ void Win32FontCache::ClearFontCache() return new_glyph.sprite; } -/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key) +/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key, bool allow_fallback) { assert(IsPrintable(key)); - if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { - return this->parent->MapCharToGlyph(key); - } - /* Convert characters outside of the BMP into surrogate pairs. */ WCHAR chars[2]; if (key >= 0x010000U) { @@ -302,7 +298,8 @@ void Win32FontCache::ClearFontCache() WORD glyphs[2] = { 0, 0 }; GetGlyphIndicesW(this->dc, chars, key >= 0x010000U ? 2 : 1, glyphs, GGI_MARK_NONEXISTING_GLYPHS); - return glyphs[0] != 0xFFFF ? glyphs[0] : 0; + if (glyphs[0] != 0xFFFF) return glyphs[0]; + return allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END ? this->parent->MapCharToGlyph(key) : 0; } /* virtual */ const void *Win32FontCache::InternalGetFontTable(uint32_t tag, size_t &length) diff --git a/src/os/windows/font_win32.h b/src/os/windows/font_win32.h index 02a84b63fc..48459543fd 100644 --- a/src/os/windows/font_win32.h +++ b/src/os/windows/font_win32.h @@ -35,7 +35,7 @@ public: Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels); ~Win32FontCache(); void ClearFontCache() override; - GlyphID MapCharToGlyph(char32_t key) override; + GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override; std::string GetFontName() override { return this->fontname; } const void *GetOSHandle() override { return &this->logfont; } }; diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index 040101ec36..c8dc6ea1eb 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -194,9 +194,11 @@ static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *b for (int i = 0; i < range.len; i++) { if (buff[range.pos + i] >= SCC_SPRITE_START && buff[range.pos + i] <= SCC_SPRITE_END) { auto pos = range.char_to_glyph[i]; - range.ft_glyphs[pos] = range.font->fc->MapCharToGlyph(buff[range.pos + i]); - range.offsets[pos].dv = (range.font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(range.font->fc->GetSize()))) / 2; // Align sprite font to centre - range.advances[pos] = range.font->fc->GetGlyphWidth(range.ft_glyphs[pos]); + if (range.ft_glyphs[pos] == 0) { // Font doesn't have our special glyph, so remap. + range.ft_glyphs[pos] = range.font->fc->MapCharToGlyph(buff[range.pos + i]); + range.offsets[pos].dv = (range.font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(range.font->fc->GetSize()))) / 2; // Align sprite font to centre + range.advances[pos] = range.font->fc->GetGlyphWidth(range.ft_glyphs[pos]); + } } } diff --git a/src/tests/mock_fontcache.h b/src/tests/mock_fontcache.h index c9eb326029..e6cee2d022 100644 --- a/src/tests/mock_fontcache.h +++ b/src/tests/mock_fontcache.h @@ -29,7 +29,7 @@ public: const Sprite *GetGlyph(GlyphID) override { return nullptr; } uint GetGlyphWidth(GlyphID) override { return this->height / 2; } bool GetDrawGlyphShadow() override { return false; } - GlyphID MapCharToGlyph(char32_t key) override { return key; } + GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { return key; } const void *GetFontTable(uint32_t, size_t &length) override { length = 0; return nullptr; } std::string GetFontName() override { return "mock"; } bool IsBuiltInFont() override { return true; } From 36cf6b1d13cc792307b248f936dc55dd4f20923f Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Dec 2023 01:03:28 +0100 Subject: [PATCH 08/14] Feature: Scalable OpenTTD TrueType font made by Zephyris. This uses the normal variant for the small font, not the all-caps version. --- CREDITS.md | 1 + media/baseset/CMakeLists.txt | 4 + media/baseset/OpenTTD-Mono.ttf | Bin 0 -> 63012 bytes media/baseset/OpenTTD-Sans.ttf | Bin 0 -> 63032 bytes media/baseset/OpenTTD-Serif.ttf | Bin 0 -> 77168 bytes media/baseset/OpenTTD-Small.ttf | Bin 0 -> 56264 bytes media/baseset/OpenTTD-font.md | 6 ++ src/fontcache.cpp | 50 ++++++++++- src/fontcache/freetypefontcache.cpp | 94 +++++++++++++------ src/os/macosx/font_osx.cpp | 78 ++++++++++------ src/os/macosx/font_osx.h | 1 + src/os/windows/font_win32.cpp | 134 +++++++++++++++++----------- src/os/windows/font_win32.h | 1 + 13 files changed, 258 insertions(+), 111 deletions(-) create mode 100644 media/baseset/OpenTTD-Mono.ttf create mode 100644 media/baseset/OpenTTD-Sans.ttf create mode 100644 media/baseset/OpenTTD-Serif.ttf create mode 100644 media/baseset/OpenTTD-Small.ttf create mode 100644 media/baseset/OpenTTD-font.md diff --git a/CREDITS.md b/CREDITS.md index 8826c9dcfe..1988223bf9 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -56,6 +56,7 @@ - George - Canal/Lock graphics - Andrew Parkhouse (andythenorth) - River graphics - David Dallaston (Pikka) - Tram tracks +- Richard Wheeler (zephyris) - OpenTTD TrueType font - All Translators - For their support to make OpenTTD a truly international game - Bug Reporters - Thanks for all bug reports - Chris Sawyer - For an amazing game! diff --git a/media/baseset/CMakeLists.txt b/media/baseset/CMakeLists.txt index d3c5f87337..b92eb0f648 100644 --- a/media/baseset/CMakeLists.txt +++ b/media/baseset/CMakeLists.txt @@ -18,6 +18,10 @@ set(BASESET_OTHER_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/opntitle.dat ${CMAKE_CURRENT_SOURCE_DIR}/orig_extra.grf ${CMAKE_CURRENT_SOURCE_DIR}/../openttd.32.bmp + ${CMAKE_CURRENT_SOURCE_DIR}/OpenTTD-Sans.ttf + ${CMAKE_CURRENT_SOURCE_DIR}/OpenTTD-Serif.ttf + ${CMAKE_CURRENT_SOURCE_DIR}/OpenTTD-Small.ttf + ${CMAKE_CURRENT_SOURCE_DIR}/OpenTTD-Mono.ttf ) # Done by the subdirectories, if nforenum / grfcodec is installed diff --git a/media/baseset/OpenTTD-Mono.ttf b/media/baseset/OpenTTD-Mono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..678050e5121c35c3e9bf82753126efe0c8b44691 GIT binary patch literal 63012 zcmeFa3wT?{buPMR10?t+LA(f(0P!FJkOV<;10eW*NTgn%-Y-g)Wl7w6T9Ii+yHU_h2&#YN%&3ermiAj=FAw3`&qw!i$IB(Wp-zHjma`=`wNPE1Nt>2XOiygPa4X^-TU z@0O&>J^0;tc>k%X8#mCh^z*;N_oBnc?>@B7|E-@(k~Jntm;U6)!ToB}QR%@EZ^ZY;BOf?@*Mn8fCVWpzQt@-gZ=2jdc8Dm+5dB? z)bKV+q`9Y`?B$0A7F{p*%zw$)=zhJv{<&P61WS4z zed@mxjP+~%Q}2`B7Cvu$XHh-+E$?^UrhXr_L)Us8y`I)SpKJYD|M|HT{=dyISu~eR zaOdBGkz`i@)pTzp2k(r~O~2j@}>QkMu|P5bf#oN1u8*)zyBx@ejDh zcNP|(OXd;n=yjI-ra$vv@pHkm7q1J8pX=1d@T=OOWq`xv{(z9QGjyW|7%G5NIofc!D}Y57_Ciu^74f0ut?2pAqU zoHu;N@E68gjE@_C&-mxYzcBu+;A0g-F3DBkGPz1zm983Bz02pZc^W(cPp@axGvzt$ zdC2p1ufyx}RR{m^`A$ga^zulb#`7L$e<;^1dETq?>++w$ouXJOkxHd9sT{gmrBo%E zrE19n&CDj*C5KcaIi*^u4p`)p+)@MP(kuBSztku-NdYM+g`{SwMQWA8QX6oqUFwiJ zB}Ix#F)1!}NeQW2>XCY-KB-?CkOrk8;NXa~LRu+}N@LP0X|=RQS}U!CMlvp~mo`Wn zq2X+nwn$s0ZPIpWhqP0gkakJCrJJNZ(#_Id=@x09v>(GcCw*9YMEa=oap@`P8R@gq zW$8KTbJFih&r2^#zbAcO`hxV5G%LLU@Ls%02RWIUz&K;;*~q4jG!N z^pJF3dQf^ydQ|$DG$TDOU64K@rBMEa^tALl(x;@KvF&WHbUWM4Zen|+d+^Mg*$({9 zbzwmMPX6x_M*k-BF@;lgi~NlIn*2TaE%{xjhgF6>hLeU%hHn~vV3ds!;|k+_#+Qv> zHNI~Af$^UTj0M95mkYjKC>0JD?kl{j@OQtogF}T6IlzclDa;P1T>Se!2Pw)&Fb>SoT^@SY|Arw|v?1rsZABFRWH;qcvt7 zwccla)S9whw!Uors`Yj2KUv?i71^vdk1cHLwvF00+4k5zVtc~&Y1ONohmAcpJzEk&R-QU;!v@TO$T_3Bzul~{cSL(l6|3>|f>wn?0 zx;(D1tJ`(Lb&ulN2`U4P^HvFjIZ*9YCY2WXzS-& z-)Q}5xI4Trd_Me@@Y`+GZQX5q+n#89x$Vu!Xk=4lPvl7CbmW1^rz3B+cen3tztH}4 z`x_lK9ostgbsX=w)bXW`Yn{EFn>zP)KG6Bq&Yvh1N{6yZIjcOSd{Oy9v^wgGjz`t# zh3I#pe;=!ewZyi>j>pc%z7u;ZUKSsZ?~Okceb}%{wfo22zv!vxiS(@M+0*k-Ppao@JwNHm^agr&_ukoizW4LJ zul4>-pVSxXThn)M-xvG7*Z0G|cl#UrJNniBr~1Fv|C0gFz_x)020l0NrGc*ve0$)n zfop?BgVsUMU}Ug&aMj?J!G{K)7)%e94Rs8uLuZFB4P6=f>2URM*BeE9V6 zy~7U;pC5i=_?6*58UFV0yTkJ%g(KA??vcpIiji$2>d4uVXGUHa`O?Uhk=IAw7|EG~nB zJOOi_B;DwiufV!x0>_MCeUchuU5edW=(G4^gNAr4V(?WMT+AOIG(;7<$y#AxUbEMN z=2+O(;&QdDR&6eqjTMww>#ZdPOl4&a18sZyn9c37W~SsT*GE-$t#3;o{bjbN zgw^V)Dl4n|b$KR_#Z)9$5d)(l``fCAC$CE2qCG!X3 zu_~>9tZ;mY$I+wP$sY z!K12amHzN9F4QzcOGutKp62$#5TpP+(-O7W9X5X~XmcBE)(Y8V^Tz|hc+_fl#3KOr zpq#K3+N=%C))kMX(?|9tr^CYo4c^|dQ2N;3*T0}oH%^(p00aj>GMsHn{5@&{Y&k0l*g*LO*Z6H8IjBzK!bpz{+b`CHfX3rc; z46sgrCmvcL-&to@(&@V9-uAk*Vz2A0uW`6K>QPqP(bHU?Mp=D_%i(Z| zdZ88lK3>h`kjs@V9j#TR&ZP01naj#}bFGQ3bCy=Mc5G4DUX*OL1^(oBZdRSbht5=h@qXv9EoE@bRV^NYVPE&T20tf;`m4WSp06~Fv8{x$?3(KDcUfA#@YSXb9)JJ4a<7DA< zQk|YwL0A04;F(S)r}O>*F0Ngu@&s6CDW_#jESdm^NQ;*|0S=H>L1(Yu=w=tCG;thB zy8eQ=mxb9iHbY#&?6rB>wM-eCA+kfephf(W1|OEXG!B;*TvOv^sDrAUm%yJ9jbjvG zwtG{V%c^`uy*?`R9R9l>+J(g8{VY=8t0=I#SUqzWD1!yDCSow4XcwkU_C;hiV<;%D zw7MJJ*2>}n!-6lFsfN+JF5flUpnb42ipSgU@2IOUE32>T@b`N?OA9uhJ=WiU?CeHG zyAWf;JMR}DVTqcfHg6m&QG7m?zWzcQx;j<}6=b-ut^*^mRxlF-pyG@O*$1}S1wxi5 zynavSRrccb7uZ;h14MJ~bI*N59&&UCQLIj*ur^vVojP~=1AM;3v+Fp_O%Be^{JsEK zZd4(z)z0Dxtc9~lkKg;~<k2 z=F8{OiQNe`a}`K-C4Ktbxznf5Z66ugo&s`EGugJR&^jfM93bMb1^hl2@i^YD1uU4i zd+u|py7!ox-|jpMpF8bTohgMk&FWLU@w_ns|A3od0E{~I2%wqSiPa5rMDhYKSDQ;4 zq>*Mxs`l7{OeT86kOo*RL2pK1Aqvn7TwBpKt1`fzWG(k4Ha(Vk?XitrY)n-Y6^zi} z*}PZT9qc)&9KPqC!^-VF&AXJn7R8Bw^fo`OOivSHh;ftO%?@2#d#bI%U_wU|Sa#^4 zjoO1AV}p;eDxb3^^Um}SE6SdIjLp!4(0pN`GT!S(dGd!0Uk}^$=0UHV{^W_OAhdi? zVpSo1>U50q04x9`Kk#2Uydc&9Bt@uQ&TRgscvBPveHCItW(rizuBB2W4v4;|LHE}H zJpo;yv_}2J0j@!AAg~giWZN{yqXo7Cf4m8l0n{MI!G#Mbz&Tj(8DNmp3V_GK0ALQj z4Ll$muPBgpL1`v!_qVqC?d|bcN18qJSakB{9*4iR#cvlJhJ_=84K_<%SE!|1mit;2 zW%C(Zcym|lfZu6%DVd)L4kVrn*#S0-HBhq!)QKV;W@}+9D{q4Uu5-C<@dwN(15=2A*(?)0|IJKbZfwtF4EsJ-Zg}uCH;I6a@zs;877QIN(MExC&-7VCjxRA_H6U+tTUY zmgYV%^!iw`EuCiJ>75r_nxEX7*~wm4~H;uXi z)(#8ky(<>*8_f6wNCN(J>h2>0En#=>+wj|Zyz+k}OIk{sp=DoQ?39et+ z0`l)T(vi8Exw^Vb=~^xDL-4XrNotDHIt&($CI@9qc>%a1fUR@;r~<4nZtTBf!)C$4 zH}~A!A8}S1(`t1-v#(a?tdX%;Aj`C^4dLd9yL@^HkI%z9E|c?-VvvOxqd7`L^QWD& z>GZ5Kjn7$w=kjM$pS=wE{{{JV4lKb3iH5Ou()vgL=#!Wq3xjlKuD<|QlLq%Ag2>e` z&a3a&YlEbz>Qr7m%rLNTAzTcAOT@SUGK0ne5Q;oe+&FML3!V+92O5jhtf1W1ShEm9 zHI24%(raearWLyf+p>@fb#ESMvea~VeAP>URqgY1)L5KZx)$?BfheMRcAw76Bu_zFI=C&{j+J`U@)O#X0yuL$Y`wn9-81ttx1p%{T|{{qns7&UEj# zUO?;m3(YI~z25#6&9RP-7}(JQ7?+_9bSi3whEfcEhR)5WsAoy60I#Bx??8GcY@A+r zA7l~SgjvM%X!@{FENBdSP~Z=t-C>sJ+Q!<-{%5?3qWY5|OuK}O7xrPZNRU-hn1F8LWe9Jl{uKWdihXdYUE+iL8Cy5N^L2i3GL6Hnk{ zg~AAx2eL6(gFafn81AlB&rYY45cm0T>$UMF?rnM&h4~}S;WzjlxGJg55yn+aa64c- z79i4`-K5|_&%+`(C<9-gS()5&I27v$uin0Wb-3r|$!PM~70E3}g7Nljk-@Vnk!s%- z?r9D6`dk5J_dtA0*hXdB!%XgO(M!8FhoLa!^CGc=bNVHk1X@Bi;(n%Fe?gDHUaJzP z_X-24hNwy0_~|?P8;gO-kPaa%GzC`eU!^E`3*dOYVGOR+O@T{YKd>h ziY|jEy)xC@QfMC?-P@98{~=x_t7cPYn*tTe6CeG9RYrr+$p6Hf_KvdLtH5Z4&EHsn zS7C0>N!|hVu@1;MfM6+r$e`+q=}82mm?Nyg@|8hPLn@g}RkVzy!ghPN<@W0C5*LEU zGFQjvckZO+t?5oyJ`P?MPQ~MM$>f}U&E+t}!$mwl3QLQ@;t!hqmf7iPT2JZS;F+J# zOl79#=Y<}S!!=Ny1=9*`FpDol8@}p zibMu$Ri*nwM|RdYGp{b_k63qw21cv&AbSlu*Y`6`2G3k(a5~MtFW{8E@ie;zIDs}S zUK?MtAT_C2$A#uVW5lYU>#klui$|F}0o66d_6p^dKR2%(W)?~!iPS25%KyzT;1yoFU1kZcRV4$a@Q;lUSQ zd~o{cs<2vLud1HV=ESNNciLGScKR%qqQ2(FVKPyufk8E?Bvsg-$_oosCo3^G#Wuf} zl8vU)N_&Ok4{5w!gI6WIjF3|WTLsVanxjsL*SaVo^980AHXn1cZWycECV6C&hw9!;-<&1~v=~1e=D^!PRG0fAlk-`6xbu zY$n>to9c|ZMhBZ8+m_n)So7d02bX{uV9NW7xix#Uf~f=iTFC#9M>Ci8?xp~Sfgr?~ z^m}h*JFJSn=H{SQ@}ReT=w5DDT+mxPG>K@8g{ga)sexciFYod6?CkT9cjO6l&!r~2 zR(Hgx$1|H#n`hLHSS$}0$;P07%i1C`%*&+2lUNpy#=6*R;bdi%$uZ&%HgbdR{RU52 zp-D9qS1{JrrE;}x>m7Ve?$+=H+AyTB3PKmy6bLKg`m!v;N-CgWo@aXvzP8cC`k>1* zQD3JfN4KOjsN7CU0AK<^O_)jPiO&AeA^;Hw$kBf_Un}^!3+=@m3$zmDs|vN5Msr{t zX=)(z2s_iYIs-9JgD>W*m@E?Lvu2S2mXYBfHugao8Yjt{YD#s~!3+iM3iMw_b{ZD8 z42HuEq^0q;VCN!wvd~Hox)fFKoRd55mxw^PiI&FXTxU zB>^=^jK<9N&Sm}|=9!&?>@bm;&%C9~&5@)CoXp(=KGsZV>5pTq1m83b50ECa8P&US z1JND3;JqhGb95zuasrrspUG{gXWAFQcQ(ASyMJY3XS8-U?kleSECTKW2VF0tnlS)Zvg@%JUB63yi z5QBt~1@sIP*8D8~gA_o&8wS`JAUv>s)8lySTFq$-TBJ5-9A`Pb64rY;jS(XVYOJM| zK|~`iEten3md9ph z8wO9T`RHeeHv`Wf35}0}2eUJoM`&jA$BcEcn9%}T$AIdYca+RKDZJ#s^*7~!LJD0D zMppzbG6*ry`V1u87~)Y&f|2wxk(wrfW;!(i2A7;8yH*+3(yw6vbJ;$VEgY6HGs!K& zL&Od0;KI{$bK)JCIh&m0OYO~yRW<;~(d^av;@?*u%I&k2u2_`xniOzV=aYJ>m zA}nz1pq@eZ=iqm0L38O0uwWvsdv#RC)O^p*C3g=Eupx%ZHit=XfSU#3Zqe>%*Cr?P zeMJPN#r~qn$$XCy)ldOR?jIw+5mx7{hin|cS?D{W@h|H=;;>!dKS~0W<9RJ4$%#bO z^4v&-i)@DDt`~Tvz>b-Snkouf$^8caB?b$k^Ua-BbI=F#w(Kabt7)!LnxnSrCJzb> zwvt+B$SF^d$2^%dG?vwul-k^GD@!JgzKYsXEN+^QmL>x>XtFQL(zj@h1-)>)o6#4* z$_ig3%#2wR@0P4DT$psh&@^ATyj}MnVI3iv82pOcjY07+c)}BH7E%>?q9X>ZD{$W0 zgwfWKPRBQg?c@Wi4nd}(FZS@}xUad{Cto>H+Lq{YjyN(Oag5Z(d)i8l-(EG8T<24K zYm-Bjch{}=EB^Ixy8vbw1o=PUvEWh`8UEr?a+{H;!52a@UV`AUE|YmnwRay_m)zfN zPb+bGXqKCd)Y-mGeRcK2yT)Jx2bYtuegh^(aFGf~A9e8K4i+(xUrye#K4(DC6ZS-qD-JtTjuF*R+GBtB`X6EWk z=eBM=w^i-KOFiu9aNyqTC4Sg?jzA{hM!F6(05f>B7NDRxn+SUN3ntlHbFiFbUx)Qf@ zFiQ3cq1vf_K@R<7R2gkYRl*TyZqySG8ctFCLy`BEWCM7uR5@6JB^X3 z9epg~-fA;R0uWqm1YqGgf!_4OLl3@~b%{XYo!WKV)P%ag*MVJgf<{cVLeshh(ufvl zpJY{4=jTZh=AUu^jC6h;PC2~m_=o$ksFIBrvRoWCfHXO`GFM@@pjZ;&&jz1@M9X7| z1Z+#C8brTBENK!(K-d7SBv}s1!B|9Y#RA3E*JXjut|e8cIz6kZN_ly85i6=LD_4@s z!+KsJg=Aili|poVN0FSFdOtXe@j&|GxC5?gflYwG3~`KpBba}T!`w_ZTd;FkM}!JF z$fY`XihPAxk@!BSSC06hkGHvD9My*uPqocy7U zVXHGaw%Na}+o_mb#V?)ZPN!UM4c3Mg zgCWTZift8kr_9@;_R%NuX>g96fd9t^#+*_xy=q#4|AXR1H2ecCL1NW#=25^y&@P3b zVSQ@SK5-)`Hw{do56Ja8-6A}J=#t0uQHsKt1p=>@+JF8BM5jCOwjQDIWH zl|t!`r*S{^O_Sd}pmN|de9hqeP<+S=$*~5G;6Y1b+CHBpJz|2{D#z`JKy`v+eIwzIXX@igaJD zeZ-h&%lZ89I681>h&Yx$7)kwH1B}{Q8GOjF#B@1Gii!g9z+z`%$pv-a`^A-BAU!!Q zuY%Uuiy!*i&GA#Wl21*W7coXevjY>zE5OUMV-#ceEGZXbUsA4(eMz}C#--)FecH{u z=()W8rRAdirRAc1QLe#?_+L5kR=~<*wpDq_PKD@7K!^-Enn6>Yc9N0Q39%`iOgg(F zEszm1uci?0Goz;0JOHpkr#f_CQU9%0#}xlYjEV{ z#KR;7GU=n7%P&-i;|uiRNAvXIB$x4p+*Jp9ii2rrqA3IqG6M+7lndq#;oVCFEGC#V z5YQC|Cjdq@HzP=EbM8uWVEmSzi=-zBkB%=0AoaLced6%m0;A^|SGV}KJmHO9Z zXbx+|a(E#xDc9h*q+Em7(sF@co2dOfeBt^|C)g!cK8i50nYCbwbn1im-~YiBBDH#9 z=1$-7xjW!aqi_kjpVkr)bL$1Rkxi7uR{&E)Df#0FMvCE`%OJkObo%3;`~*cNJqwY8 zqLSp>ueZwoZO_(RWRi+FAyot=EgC<^FYMUCYXQ9Yc$St6xGYo7@oQ zjz3r{+OWH52xC^<%)u9O1Oy4rEM!+ixV9~onv9Pc zjnVkZhY`lQe}gi13;{)ObHLC=miMO`gOC*5)?}8~@wh6%>sBp+p@8k0CFKIPOUgCa zE-BYwxU^if|FidLe@VI4{*rPDCE(RqHSm)88}T|1_I*hfyHGM6JU&i=vu5(=3{l(V{3ly^KDw`e$ zx~gk!!J^{KWga9%Z~1sA_#&)ec;%OiH59wa7MBayE-BZ>zO-E6?UHg0=Da+MpI2}t zB8Q;<+qK{{-Gafb@*>_I*xZM>+Cb*B&(IincM3rb2&MU~}E zb%DXbK=aB@N2MVjwuRC~^eM-$96ZW_>!#?G=E3QMD2q<&wh{Qu)Op<}1VaJ&aDiZm zNFz@Uk6I+}hKN^OFpmPSJOqZN{-5infhWLm(~~am~Ef%FdyIO2^t>4 zmRJ=4eiARw)+c^Lw5iSe()Pu?FRjmY4mPg$AJ2vT6YcPF?CQlU9}Z%?%hVTiw6s1S z*E03Rc(e71-ubw0p>Zv#A7ooKdc++I`XlK$jB)SDOmpqiEwC*7V7V>tuzZGGLaBGtX zXfaIr+O$+R(bmMJ>o~{JrS&CVPOJPP81cEu*2m*Hj|*tL?`L{{Xbw1k2gPF!fMGeD z<2WI3E{iK!oD*}*buq46(Avj+W(ncQh7pMSv0*SLe;KzL<>sW4?4wO&O3}kY75WB4 zh;v~2OVfx7g()vRCl6i!M$4L2&CRRUv>>1d@#xx~K$2n1&~AOO21{_8FLdlvQ?wsY z4;S#}UE>k?UVc0!=jUfn=fx8&a`}@8VDMyv3$hoB;m&bThHQ@)#tU1`_t94i*DaUE zA7J}l0(j^TLJQCD792YWZb-r~x2PL1_LJ9#Y%s-NYm<2~8e}^oivmS4%%P{ShG}sb!j!g5zcGW0a8C4l zqh7AzT##)e_b@1&?#S+1b4%V28Jrm0FtX*^7^#y*`S~ncFVvZ9)!5n@uF5h&Ca|aBls6ZO+Z* zw>bCsS&ECH2E};waS47a1LKw}U#hccvci)38XxBLl()78F)wN0IOd1jL>J$;=y&lv zjTT6Da|$^rXYQkT7w$GSSj@BoiCI)OM)p4JMO$&8zp0|4ssF%DS)*U`3iZgaGJHf` z(Tup^iMiAq4OG`{Ca|X}fgPu$!yDg6ho@~H6hA)5G@;QUQ~@|Hp~%lx)|;Kh^@c_I zyCGEF?C9I#^KI#C3WWS{Kr;(eczL40h&?0nBJEwSD=u4m0Fi?S)~YLeQ#~uO$2Lv7 z24aimMDQ$~kI)*Z=`vhSfD|F>FOoyD^>gJk7szX()z{k*xXiNk7nU!rFKA9ayto}v zj;tw*+vjr5()ya5maVVTsB{nKj$L{?djGZZZ2g7(T&8{0#CWsy7qyS*ehxSIA+Y9O z0j}P|;ki?P?xOY^7nKtqpW#o~`E))X0}sSb4Om<8#{(VB*iA#IivOf2Ud4YH6tM<~ z*rp-G3N#S!;~p#WTII(#(Iy)1f`;CS7owb$l9E~;uY>rX?y7jq3Is9K)9VGvGq&sW6gB;N7W1M;A$OMGf0{99Up4(LQ^(5EMGP?gU z8b8a{*WswqRB&kEA3zEDU3OJf4_1v`0S zK_DsLdYzSJeDE(~)nZ-Q4Xa-6*M;Y^%fg+GEc}t@p3D5xb8IGZJd*xw6W$FT`RR*k zcn>eC>g2(LlaGHgQ$e4Ah`zphL}VrrmL4IY1;Ao2?acIaeh10xOdHo0bQ9!90M4}s zJX{=`yr^YR-{L^!{Ku&3{flFk7d#OTTLdtRXNtL_cuVjHN`S#*{vkShX=`*6KFW6} z^glhzEVDfNA2QNA)1dp=-2Ko^a`&4k!iQ(i!2K$M@+nepE;XOznwqN4PABKooEG+x_|19B^n!L1xS8C;)SL*YQzVTRc5tmL=PVt}cb|d(RV?qFiLcdkSlCzn` zvE=U;NzUhsV2Ae6kLC9s!h^%N3AhU=03y5d@YF_qW9G(FwDZtd)#kT(Y?UShV+K_F47mOZ`-uLFVMGtQ=2Q)*H&kBHd;!n8fqeSwSn5YNKHdkX=$xx;eJE( z33`ae@8P@Vyq@nNq-e=0ik!&rKVmEE7(`<~+;V1wQ%`5!AxAsZYuaX?c@@p!CG$5L zZ@E;1*87+Tn_Wr0qP<@5&X9u~;pZ$oGb46+A@_sJk-{?b(Uuv6DZx#{1xjE$a9x8P zQ6v{5DFn?3Uj^U!gdLh<$I8NOEb>J6ox9dqEOT?F+AZ7e>dx(AL36n_Y3x|HXx#Kq zL|LF4fB;3YE~r~Tb+daIxk4p=mv86!538{TLe{FpRs;$K;Ndv4PP>!IvdLUtIygQ! zi9jO+E^)`drJ=#nJ;wWjC;}|31gYihddf1Y61(<(Iugc)Z7N*XEkb*`T8nHIT#db* zE3N4EqI%o`;Sa)8z!hFHoKQ_6Ux;`ZNFrE6L33J+2EO09==)0Eu8QZ=J|Dmqej!G2 zg9MD!jt6!qx4(S5!Be|dPS%R%sUK;?YEkS%8S3X52dA zKm?Wf*xi>79Jq8~9yzW;tK{;vA6mQiLu*2A9$tcH=`kC?B_zGTGy#VYCqsMhK;{US z#7-lcECg*p%Hhfmgy7PWlv9t^U`dXdwLxncQYP{FlW!+^miEj*9v88m2wz$**0b6% z*uEst)8G+-o^?(~mBU_{7v)JYxQOYz@edU5?FcH^8_#=+hzTIr+(O(+FF`F1Td|J` zngffP{NNL06(fFZxbY9@H)aD`MLA!W@H?WfG|YvmM!Vwoz&3|CIfRgiaJkvp{D8Ry z^2Du>4@_(y^Lw6h8l^$sM3uraO_!B(N`Lh=>r z?&5nXLkRI9`e(qsupS|kLW;yk(zf-j(qgQOo~!RZBdQP5y)cY%UMKF>woYT!()2CB zs16w#+W|uu-4TLogaYR_DuYIzDFvFW!NsaPW;BH$A=y+?T~l3Rl3Ctm<|@L#*7Wa6 z_{zu*qasa8OWXR^cAKreb$uJst>u5&eBbf@&`MGOGmr2ANT44qF9 z+T;Q@#SvjF{Ear&5$rHO1biU}o+TZD?IVyP@6|t`95?{EaX**qNX^cNHP1_9iDIWA z5?xuM1~5q2Gmu#!g>7`$Wz9_@d2sr-%x^&a7y<;XSg;;~W$}FgIanExpHu2Y=bL!H zGdt&z75crmur-jzsI38*TUrCq4*jD~j)lKE&j6Qwc=nU`+wVw#B)&lH=V7Z@WAc$S z4}O%Br;qULS7+r(z>E&Q`DqmvQcGY(y5Ry@fq?%485#58O8gw;`7h2D zfLSAq!!{GbHoR!o$N;;rAOA}E0&+A@c~~%a%p3PIL}1b%^@0|DSO8&_l0Q40X~JHV zSEr}*Y38>zuM)>|7YT0k4{{U03xPzTjp_84%;T|Dr2l01=_5l4({d8-K4z7P9gI9wv&xQL`FPLi9Rk&_ zyFZ)y<={L5j|aKXhDdUx@U0dsp6XbiTHld+`b_GcPl9V)-m;RB1BR{KLNRb3oR+bt z@!os$;O3K%^+7m=p`#5jN_&8yWCZ9V&?g=xQRk)1OO9x;DK!^t#72VTTq+QVIt-pa z{lw}MJK6$ROX_d`z~qxpPF|(!K--QJt3Ls5mcP#P_=HvLlq3yH(de?j-M8FtY#(1| z9z}Ds{@f5e66=pBzaYx-8*Ey9T@vL`LbA_52AphtzFsY}jy*&5b$kX}@=(N_1=%4G zARhoIXpe$DVe|1=C(VtmJJ+FqVW$^@=_B%7%kI#wlkxU~g7)~yU7_7AgL^vd_Rc+n z6uMvPa8?HK&@_jWvty%H{5%a7}G(O?b!+ zHv#Zbj1Qi(2Fi~G9X>xB5bOi7E^J&z)FU*`m?;~^fh0pIEh!K@5-+{Dtygue7P}-3 zp1U^X(gK07H{640DmB^}dr$YZ14k5kF5qDWG@=#+5g-&7TaxfV1Dvmhl3Ht3iXmRk zW}U@uRY<^9-NQ$^Q?awRA8^&vMi7|YvT!wc;7tqh-t*njexFrPm7u5uV#m6w^Fo(c zc*C@#rZjYRY?|*ujYrlp_T+O~*pjonj50B)*oVq@q&DyH1;+b#Q|GmfsS*?Tg8sv9 zBX~X6(M{ zQ=gJ2_+FBb-_nq3u=qp#+vc(HwQDxEul5jKX>$di7vuv|p{dZ}W@0O~6#;^z%hGlQ zL_^?lNdE{4Vm?`?$Z}U$^$e~ErMN~>6=`ng`C3A&`qr7ioxn2ZlcCkaJBA54QYu$4 zs%^z`)6l-ImYcTquP~9ZM|(c}C{?g&VG}MnPV^nY#Oic^H&$PAbzlF6JVbe*a_g7{ zIMzx$A(zpQ`vs5$#$WWwy)o)+7qF>@WEl{6e+O zLp^~&&roybv-DoezZ0II??9FS<_lhC>BH?LAAYyz#jO;ay_L7-*G-8AUSkNBdmCLD-k4MMJm{=o;yMqS6-|6aoaFcJq zN{}r-Fxc0eO09et`6rg*=kB#bwfAAM8${%rGr46nwG4W$JzU#A5r;yQtqu(9yZgm5#CwfK_{0&637`9r;dUXAi8M(~$pV-Y=R)8L>Ri-TlNLro z@(UNE+Gzu-JmFb!&!_KM;Yp{#TxXTJP;#ufc`O+s;sD`^R46n@Sjln18~RnlAE!Mc z(;xp^_QX>cFQwC$SmP!2#P0NTa_0#=OXsV?{<(ZU9We66`E-CoB(J&9K-7#b&`5=N z%+q-A@AfG8k$+^iHo7x`Ks%lWV#H5D2W#RqWJL zsSY$uG%WgMlhV1Bx@j*34}K)JjqfReZg?;P-EkJbN zLRn43vLeqdUQ1-iLdIpa{BpLB%ZN`cuCJA6>x(^_Sy}Kh)z|0MKzlby?*@xS9uNx0 zfaa5CmT58$rPa%sdB{k)bag0UCQ59STQ{w+=n3g2Pc}3BuS#a}#8SabrjA42_2Sfz zwIrt^a~VW;?3nT)Us+Vo%L@z(1YxGc{thEgECqSK8tZFJHTI2lA$P9Lt0==Ux1Nru$Z84H z#oP@K?C+RZ)1p??*EQR#N$zcM$LazWD@@FSms~;LZ3J&i7qHTyz-xl6p0r9Ere}8s z+&x3cyFmNhu)&FxnAv21GfQ*9D07)+gePSXa1i8rx)>hXCy86-+dMaWHJnjMVbjP~IxCqL#Y_ItXH0(&TU zkNn5Ln`%f49->0%h}9a;2?pQ<(%2C+M9z9Fsk<)8pSm0GjI}1!Uf+u0#uVNVS^cTZ z-+U^a{?y}ZPp=KA_phCx-LO;iDP(`jBQpUW62eXl@L!|G)3J>wN5Bbx9=U_bXw)7I zKd3fLFr}=FC|al6va)9jiLz5f*9i1gyCR%wb&`y9CE9fAgz_IE$_NxqZEOGPl(g=+;2UrhNY?$)rez z#v|wuJt=mgYU?L(r2_!WW>uBRpJ^j%jVf?@OM7}@`c-r{*N0B(!*5C6L$ZBf2HxL3n9t`m8vG-oK>#v;Owbo7 zOOzgz%J=z_o&HznD$Vhb2GSBK9+BJUX_b~?Fs~@WreaVq5GJsK9qtY%JN;E+rB=ht zAQu#sS)6_wd$DnN1nlIhKR(=L(NgVZ%1Ybp0c(9_Wg&c*nX7B!3RZ8R4t1W(1x~Uq zVb$UP@}El{Q}NJQHMQWOv)M;clexzc%fO%h5X?8$JHmhH?p}&{HjyAq_zs6ER6?i< zJBK)?bL?klRt^{himS9N^Dgo?YNLW$N$`o{Ct8qi76Ck1CL#7IY05Y}=LFKv%|VHx z#1Yeo0p^jTVyx6gDfi?f;*on#VXYFG@C0-vtaJcufHtYBBO2t>+Et@JK*DiW+7_Hfxa= ze!6Kja#J91Q$(FM7Zs_7Qp=inOK+;TCB8=cp8tHn0Qv*Mgz*Oog4dJ3xTm8WF`?i* zuToAHLQp|#(A2~oM6~8aKAq@y&ujESUJ3+SCqaJiK;q50+jDEi|EzCD!v-)OFjByY zBLh5Y=~;yt<-+0$n=9ya5;hPbfXWuIOhO47Qm!9>!@t;%lSk9U0d>gHWNZ1cb8!1@ z^~IRL`6yWm{*iBk&pVtjG~EOsKIgyLywEwALtglI$P1r)KE}>v1PuOt{W`#QS{V?L zp?P;$MWN4G8>}r(iu`X^OU!ka*1DA~D$=@CV9Qg5%oAtjm~NBl!%eFF6? z=kpQyd`P4xfgs=OLmT2!kZ%|JeRl1DzlRoQTx`8%AujX$cE6V2N8_(KTqXwV1uiS< z^*6-=b$xUW3zQBwFSi$B!55Zh@BlJ35%%P=coG_A?FwD1x!p_LPjDcf1Dw-@6Eive zz&)Wez4w;>Kt%GQKK8}Gi~2%;)~oaWQTO>avTX(8a0m)TUdk<(gDwptV+;HH>N2*}kdMUs2)j+}MG0 z1;X7uEQ-?wGFKa8!*Q!p(>>JbrS*2KTS=^6 zxzhClF?d*Hpv2=G8DwG@Aa61>V;_YT8dzA5?#rqNS{ep0vsPAY4Y`DRkY{z*^#eTt zgHvrC>GufzfU^$%Mlj=hHEB$Pvh?X#Up}im`wTox3S41v%oLNngBgto*?oDuyh^l9=*Ki2(!f#7nW$rm)q|1TqOj?Er zN~~(2>^SEoxW*XEYx({E^v-xPIsxn zQ0jIbn{EiVx#fu+!(-uwp3XhT5yXqsyfx+KqI5d8k8&I1#eEQ1jXffD zi+u^~A8DHM<`L6I{xE2844NFyuiZpM^iHn0DT603)!JuVBTH2;3|*@6%UG{6t+;MwO9fkx{&WX~{yVyop%2 zVkq8!@3Gtd*hzdI%pGTbg2{(D zZ`Widv|+&0HLVf(RCyz?fYBO4D~DV@JBt)rTQ7Wk1LP%pJr0%;qkw~K?fvN6)iloC z*BU=ymy<&v5xHT;h1g9oN!)QwJ1tmPKTBY? zBVH36NWX6C@wIN5#VG^wgnpiY%hzd!8x}lCQ7CIarbt_7XpS6oRx4&WisteJA4<2D zpGap`wT3q*j-5GkEU`Ikh3Vj(Mvte_1BOZN$@AM&+s~7aa*kbF6Hmq0&|B^~1P=k- zocsefr3gbI)Dn`LHX{Np*dj?n zXtdAE7ptZPeGv9}_IK2`JUZg@3B#kve@gp-KvWP=uuh6TK%+uZMLKw4c1x?T$Mkx7 zAXpRcpt+hX~Xku#g8)18N4fXJs;JH=xVy%HMdo&}3Je-LuZ z=RIgT#ac0Rpb;=RI7PPVFi!uVgy69OA1=<~l**YoL<3A*L-7?sod%i|Mw z^ZFEd!fA$b%>kxd4&v(+#WHC2Xt5Ab0JW$K;7k~PhtA1ikjxSCg;-tkLR~Zb&Kzy8 zC$n{y4zDaz4?71bKAD=!?~~Yn%)U#v>*cg}PAmVZUe2FSF_tujRqPv*B>XcA#x2G- zx9mO3`0_NlRq(MKomk*&UB(L_d~ZSSkXY;mV0++~n8n|+ZUFcwkeEZsjt_IOXpb$I zl(O&xJwfIdv2mP-f{S5dz*FfDs+O+;TD+eE3IE{2;kbjCCAcYKZi{V=2-ZtG;sy@| zdm3CLGUlH2aVI!JBYeIQJe)9HSM0R#5oEgTW6ui!AqNQhkc$mPa2dZ^x(mVX4}ru5hiSZw~J zxAz;J5DD_-D6B!69Z@8wf?)=00roLsHw?DN2we90Bx*9Z`{*B-iC#HJ3t=*CFk3@`oE6fk%)1@8Hr*3xa>2z z{6RZ~3>qj52(QFWp)P(1F3!J27;UK~)XPDkUu32(u>K1dGT*!aBTIv?+g&4|k#~9T zlN?r0VQATB74gW*KIWTj78+d`|y_0`VoyIG$j$rQ>ctzfv6!STua5-^$@T+VLIwK6Kbk^6a+W8!GKm0g2 z2OIZe{(sZo(VzS?;2jl6=I&-f=f{!d@c1t|10DgpOV5Buzh1|DUId>hr0mV~9qTkd z(_3!Op6Q+ctcVeD(I9_^9cj7oPzM4~L$!XJ%!UF@h*x&j;?Zcc!8>$hv}tHC;A?hU zeKAKB+CG47;k${a$q|v0OO8BE&&-yi4{2I?q!Lk%^=LQF7Z1uETK$fN_2o{jypxw> zqF@6~V@)tC5}k5PA-I(Fn)dSnW+`N#rZ`wyoAeCv*T9dEU|P!zPpFA~i^wTYalfc% z(XvtVN_rM*ssqyF{0JN}3ZHz`hOEBdccOhxlQN!!jN9Ow3-)>HXES6^SfB#}kjLWG z=TDvb{3A!Q`Tq%baIb;ymy1_22lzS9sSVeD_<)?8olho{NaA#$4yRYmgI4fRz!C2p z=S*_1BoQm2GLpMk7*O~i%3wFp%C7OU)7i2EsP_wAc1O01?>D6~xlfc~+<0*r-bWf9 zV!9wEli0&~CwE66pC0$>lSmKhdKK<>I-O-Y*%TNEDk5zR`LXFp7)rd-g)IPhp;`0| zat6j7mK2Nx>!+4l6wXq9en)}7g^{^dM^kcgtj^SsIZgSCfmE~h+)a@fkO@r~~ z&ISv2tNEuFXQOA_w@lo%QrZ5=+CS#uKH7O~U$5F|`z3KSX5gy6R*)#b#Q>lqZ1ISh z!aAyLN#zT0-k7)^M8`$>eaK`-lZHRyZbF9Oas(9Hy)(yfPKkkJ2krP09AJ_-VDKC} zGfla~^jDG&Fwy7o3aF85do-885lDkrw@v)4u{fDW{Ip36XOWo@h5X!PlAO{ zoNS_`@^vH!o&wztnZAMj4gwl!8L(fHN}I5eQGm?c6bFkCviL-AQ&G3#?o|g7>aC={ zUcD2?7r>)n@HF;~HmOQz+j@j-(=q9hu5=nM1to7h)zTp4Q_SsX6Wj|iE0p#*tHgpG zBeIgm&;kje%tF|R7@@^wPp4ItK^12yj&@wc;S+3T<7(Q`qq?n@26s3Xb}#;(xk_E^ zUQuuGbgthPQk%DLv0bD@7q1QM@^mLWILFcA2z$eAtC|-VFn|8BzIkIIy$rG!={Cq& zr%g}(v7-PVcBs%vFhC6F^hKj;yg2Q2Voy6A)m7^4b~-PV`f*^!y$YN@I8K5j$_3|- zs%ooR?@FhS-okkbo!8;TD(r>C=O;fYWo0K=!mE@Z$C3#JBzP{6-<$G^LfR#%F2{4Q3Ns2w4PfgIS_X^7yEq|5XEZ@h zq?C!Ii=CNEd0JzYfATG+PO`!(m)##qnd&1udRHGAXec7>24qXM#cl=L>cHt;1BS$a%-{c`Ui^n1UEByK76_B}S;6HCaw1zCZE)20 zxCGMX6=wW-*CiR^41YUc`}eN)z>8K=ZmK9$J$KgBB8`Vz4j`lpvRfEb^1GSmigy;{ zw736!{U-$e{|Es&y+(y&L0!XSql_(r$z)uuU)ihgFk3C;K%N&GYrcr|=DSg7Hx#_K zI9;uRVFMvtWqh?qUL;QEu*5qkQlIU;>+C(fLySFqr$1zM#>*>UZpNCdG_~3`C|z|A z-{B9%JJ%wG-HDO&Z?;dazW;;ju7P+su&&xn){%j2mcH=7c!U>^>}~zRQGbZ9A({^3 z)-76jQXE!S3YQRa9Lb7VSuW1Q77~!=dT;LY8DokPGy3{&?j?Z^BHinzUN4Cva1|Il z{=Ts$bhK%#&rj|ydWE}5R8hNidy6JF1aYDTNkg6D#SA(OBxW8oI9(KG%K7` z7#nY{F-`kJNoT6i**qRgcWsQ=Y>|!F)MxMa^kUuXz8n^(TA{Thn~L~<0KUUAGbW$*Kq6L@R1B;+I)Eixz8wel|&gx z6kgi;3CRn-{|Y07CTv~D@DZ1ZKqEMae1*^wV9y92n^8uru}3n0*3uCRR9ljjp1P<% zbZn+_MrbnZI>M~$`5rndH= z$Q87f3h^W>zxipGu|5yld65g}AbVb9bVJBlNK;zq3~h*J=b$4NZ^tZ@1Y2X?$~D$Z zy=85sH`W>~Ii5cSC+m-{2(LU&?iCVfxV|fN6-^dixS27#V>Av`g)#(XcQtC;Mj?6; zz~5)#*V&6A%v zVCsFo!ctoxhdWDS2G5zz&RSn(r4L7hDz++T%kCBDMxMN_lz^$G!{N~`Z!i>dTIyQ1 z4Rmb|+u&6Qcb7JIFk53-w;N&{bjF5m8Rbqy&G*YCM-ry>cmfT+0Jb>_0TcrOb#vv3 z{I)5@UAm zXwQv@&g3*VMQsIs8-K@6QlV6kJre>u(Ay;5r~q<1eg&N;=#TAHGM5$cE>D!0J-)8^ zhSkwjswL6owq!1+glx>erE@zEC2y-trAnP9lhaw^G!;3WKwo}Nw5QW!FD<}1w@UZk-)nKX zt%_=MiHh{j_ts$t9O>b}ZMb!v^r!Eycb1g9tgZGK5NA5&>^P#xYV18#t}88PPW)-v z&X}yxn20BoFcBnI!W{xW>o*fU;~INSEvYk4&vr#pk*?XN&lo&^UjN3~xw*CH{h1*9 zEC2bmb8~0kfRj(o&Ur1J?IG3-q4X2u%rZ<1SGZ#^0DxY(zD-*H{5((ZmCDzsH$my= zs84aFnX3(J_pF6GN$>^gGeQHvk#LGDRs?uCXnnwA0zRTwvcAGoZ}Y=aLq}&O(rQht z2HVr7-EFF)%b~WpQ`71nXa01{mfa@|oi8DbNvKd+#m8SyOcK znagL+T(%I>6xW= zeX~9Z8M`HcXLM#R*_n&*g>OlTTcX$v0jn3{s@_HRp($jGM<*B6wO}U;PEwCsc*Qgl zAR*NzudAN> z7OWi6uI=M(q2y!RVjWruQk~S>9fgL?{$|EHo1?C#O@pBUZ&i7N)4ACna@lf4dHujh z%_5YB8&SB^!rlhuiJQ zCEwjrS5sU)(i7hjwjJsaB@S0v)Z)*xb_#? zwNWZ#PVKrts$y%j>q4oN-L74iSN&JNUI!T!VlJ(`N-B$O(XP#sF?LkDwxRqZ+O-|! z&w|pK5k4%UaqXH(HOQnd%4OifUD~xl+8}*cyEdZE4eh!>^00t*T`1WRLm=)g_g-St z+I58#i~fUlT_x4Ty0vSwR1~{KySAbHgm!I5`6rNv{-`u59g+6qd{7lMzZ2I7@$WeP zPU3qAzPN+Z6iV;L_oLD&;*eX8P9E8RQuXXSa`52sgC{+q-3O&iU!t8x8d7u_+jeciEZ0PJ?n2ffp05Nbey~=D{ecE_f@>sY5sXqI*b-*iHrcH zJvdI;^S-T$U*izyJMpKWzCvJLb=!&4t8P1a_@GCLba;9_`On7Jcw1+i(xIT@ui4uj z92%!Eei{r#>v!OR)IIv=k)$05Po6q@+X+ucM`xs?qXQ)iTV4zW0fcP;D}mIL9lr-c z!EMqZ>9ll)PYJ<6)HsgMNepDYPegasZ#lQE~=uBoF#c{nBgh$1kVw8hBqRr@qs#)YlP^1zn%Ute2qtH2zKDx*h*cVf=)GQz$!yUea_N$LDP*J&fNs;{I{m zMgQ9VUH+Bi!GDu924bc$ZN%p`T#aLHR`SxVcz-|Wd(d;j{Vsm*K|tyxW}3+JZeC6Z zm-u%aVTrT}Ok)f)wH`z~jw^vJG@FMp7h=9WxH^Oq9WQ@1J`$@DGuVv#XuQd#bZ{Yy0PV$zH0w?J? zhfpHwPT`l^5JY(p*hY9p7_Il>4zxPO@1<7tvE}Y1{5+_&OYN25+acceN#2&;ll^FW zKkw}a(DzBSrPB;i+X=w&4t$DH)34O?|F5*`fR7`q&-0#&kFlNO=rs(co$n|6w5yeU zJ|JPGUDB5+L*%Y7!uX4x!i3drN*H zKxp~C_kT~bD@!(9IIK7G=DmM!?@igJ;lG7`$|ACqxp_jN(0&HjDG%|f6+@Gp(Jy_# zk_b(%DFw=D-EegpbBLdQN&jbJNM*w~)x>z(Aw50-4U#w{3OHJ*DMyK15twbvr5swA zo0z%uWxp>5#8#%f$|#gtmRJTkq6QghNR89LV2onyaXOJvj6Onf5A#S9wMzN+a4b=b zJxxI7`HJmxdhv}6d4+QrgO)Ipb||>0by^)I6B^1$BlYOcg;KdLmd%_rj4hZkzz`=hH=7&!`L#ABsb8)=`+sKoui0^_^cDVg;9jE0zx_cm0uG=;O7)Oy{gd?3Xg3G)TQ@g7TsCD4WE{hW6aT z2-+}p?c#=$uG6=Z?uBHMN_xIlr$ktIJ5+?POF0DkYr$37m z3wccafD+g+{_0}KpslC$idJrb2J1#fY4oGTP#3A?5Gs9w)X<~FKl>@6+_$Sc0@y)} zS(LToEChXRaJ2y`2wcYp$JRhmN=q6c9rw)QVz*-XgLDeza)o>mKXpH7)h=2Tkd0=L zWy|TbwF&v7ep%;ipNTGHf5A5P=lJ9bWia;*t`2tM)9GhB zzZC1_6&HV5^$?5m_}D~Bj-XXDOYsWhsmmWd*q~HG%+_uMt7O*693Q|Mq_SX)q`sw> zH4MFt*k!b%RixjqAyzDdlI|blBa)oo3dC3FkFuC17miDbzw|!Qq0lJ0a@C|8>u5Tk zWw;p2%*VTW!ERqX)88yL(ylP-e9wT(&hE$t|MReVvn@6T|oMp^NZcBwp>o9H*Rdd}^ywuJi&%SpKBDy)K) zN(p&@Yhz{vJ|4&D%;UnAOfhe0VO8ESauAv%esYD)m@k?W-btaWi_%J4Y)33Xb~9)n zPH&Rq2f2;`m2rr6AhzJ+Or*dZ;2BD%M4}+Ch~~K8!n3s6lWQ&_ zaNf>UAIG}vBvos}Kz6g;E`b}ve0Of8EwNcvHal_4^)+Ri?v4;QWB$_Sip|N{Ns8X* z)(p`eLQ$s$LZ=Bvjb>l1xi?qP-hKIgSFin{DzunVLam+b91^g z$7m;e6pYQ1S)FC3GGOJ;ti!)`j3+M1`jjN?INBCE;|{4MMz&IS(jJ!$Hn&<7Pe?hS z2l$XY`O002(k2z7!_zNkN|p0j?-DM3mHAaF>%rPeVryc3XTnAe z=B*2P=S}ew!Is+I&h@m9*d_IJ|LQ_kER+l_fonC|C1U{dEj7n|R_1wn2xH#%8E`P? zxth*d1EX1j|5!mtHRUQjf19{iw$E|XKr)T86dY1*wZb4J&smDc3oIcfJ-joYmN2f0pXrK^;{ z>#x_+5&gTVE)SiX519?QW5SH*Vvx%L!U>~?a44S3OibM~I?@8Tnxn^)J04L|%O=io z?~bvHR~R+8-oKEw3)Hi)Hr_;{y}2r=hBYg5<~k^)hsix3Cw0lt{nek?z;^Puuywgv z5*<_BZZB!_?Bb6bD|-(Y@*djLx!xm{=;VOiI1Qeg9Vs#DguaumZbcK@RZbi)QSw5o zAXXOKLuWPUY=T&L&KS^NWz!O7Qf5Bm(&-G4kEXH%*3}{em?)cS8CN#+i%?wVLqoMB|mb{l3E~k?hreh-`OU_ zf~uQqnKEL8+uu6hy*f%Qc(b+Eky_TpWkP18 zrFNaJCBF;ZTw^UD1I&Wz5+VjyWTg5Sj{5J9Eui9^LH|jN;~l2J%nQu@ra9cJEMc`) zH20MEVZ?&HzRyIilekKVbNKP@Dy|5O3dZr?+bQ%AHe+kqoE^t_uKwr~Mf`}e+|%M3 zks~YkOG@X>Jv-v0Wpf6(Sj0JxkD_nN;wxho@$w!YSDVyT0q0fpr&tH6Dq)P^n*kLf zmuc`IH0J@E_i_pAl)=xP%_{J67U%KKA}P(|-#q?SaFur$7cq-x>|I1Vk8yIxk&sCh zspTGN889lQJqoC#fYRb_2W7<-@;q>J#8J>yHB=B2x#LJmrHbo$K;?X5J#Ko1GRlNn zCM_ux=6d25Is#n3#=>JXB>%JckB~W+(S0i&%%XD`L#%{7g;r!wsqvmCFcpLROn@- zgqWyno)N=QXo;3I2buDk^FqNP)C8bjtWfykyg~UoZ*k+?yz~zGxe-EOIo!0|ly}OL zvJ?ubWs$~(;o^e})wOyj;A14gLcG#l50fZBN26YgTAgS)=(U#d+)H;Y3KmMU=J664 zJSzjn0{1{j=3wTaZ-Cjk1XGLKbpTn48u9vA5Vn@t88$j`5S|I^jc}^ z`KyDld!@hD?Y6JH{PIpMskghGgPnTgAf9izd~Rme_x%Gm{eQlpf4*1_X6DM(V74?} zEH4!M$qx<$*+aohw3PJ1WFyFqk01VjA@t`f#r%n>*&@Ue1*DHUQM%aaL;-s;>USE#<<>(Bg*ltG96rj}N2E-R9VYhxJ3RbAUb`oD7 z)w-QA1ESY%$4S>aEpY9jI#n-fZ?-^=>@^ zFlr4n0s0xx0ZpwW5t`PrACrrfBy2_?^K?*e1?y{gV9HR_37X*s6d!c(02NHY=)OrH zIKjwvm~>lsmT0Zs_KgL^u(70b&^N+@FkmJynvP*$(;CSMx?%$E!92$xs@^h8Y%FNT z%k>o+8z}=uaFW!QdR_F8;KoJ}!mQ)gDqG;fIfUJcyFmvJW(7+d>}+uQB|M|bqb+2Bu*>5_(23ClUdK6| zl`mwy7IqD)BLQFJx}jH3B4d8AABzW?Kwk)bx;T->j$kt$V~qgg zTF*c+1_@Sr9m*EMw=e-5C-tPC0hmRhI8!Q@s-?N|g1>L3KVIzv4J)u6+6BRMBI6+| z^#<^7aw!T9rsFoA-&>VKz#8O}z;2pha+-G42|B&n8pQ!7Vcou1 z1`x)*qz3Yda14e}hdtT&MQem0gk|G@U}ay$YF0u(8S3rlfl?BcciK_S8nqw~!j-Os zV;`Ya7=a5QQc$Geh0y1~U%eGJTx{!yP5Cf%AWrZpK4^JBl=S>|+yX4vTgUHrqOI}^ zHswd0C!F`$bkL7;i`z62b7;TevT>?zJO)iSqAsjp%%^|!mJo!xJ$3{K4!B?u;F5_j zF>(gFjlD`V?IT*^tG`tQ(8@-DM>$&%%qr|GX@-n|3A-64odpgGgBI(zqV*tZov9~r zi!vs&`CfM|PR?bqQ(r|$Lj)k2h(~bhRm8_8kGoNAtyQmu4SzkUQ;R?^4%de9LK*98 zG34Lc3|rQm2WSHN`C{cnX<-455Zp7Eo+}ruQ_M$6v)(ZeXTm-aOd~J{>@9@AF$vnt z8wkg%kx3DhphX=ob>YO2f**o}HX?yYb^y1Tgy$`FU=z2>`Y|g(|V88J?RR(D-BTL1t&XvBO*&mc6)DpH_ z86X{DC~+23hvw^;hiuk^lcdHo28RwdEe8{}8a15TB{iEe04r*&Kq=Y%=bzcnSz2gW zXfAaO2+bt2o%4mUEhc1}FrpBNmkL2(Xi=GxIZ+~@JYc^GdJM-X+)PyJGK}@d_znh| zT;>AXa$x1j(APyII}jp)qC$zzc3rev>ovpH0n`@DrkGp90Yh<|P?(H12>wajPU@^? znjjLMkq&Q0T}qin(h>>?!_{@~Lo9p{LPmzY>NrH|-D))MGN^{`bv zeySeGW>RD`5F~8yVhsr<(%{4r(A2B!#v$T#BO3FYy^g7)`jaH|fFcQsJGUH?AZR9u z2nVvOj5j$AdAbi z7?c)*`O4fir9!a~?8`6UeBW4bvQ#}bw^$7@qLMFHPX%)`LB4z{I9@6j#{A;7SZOUR z1ap<3bYgzCR4j}IrSkObVxd$%8cbncd5$Z-6QwGER_DxA3#wGaycr*~OdkW}{8VYS zR6R8o%#^BS!khund@!G{R7=x~v-wIezgU@{!@@CNE&yz~RGz5-OYuapT=hZK^xXWZ zO6lma>KGB6`KIx<=n&rX8u3Q) z#@gVDBMbsD`{3d5`lR@4X#g&HJ|Z1n=qIQ@rPTFZEumhP@|ypYtB;JyVUSQSWKq zv%DvI@AAH+c6rb9UgrJ8`)}`mycc?}@ZRUW*Lx*yB-tT?H`=IwB z@5A1Au*Lsz@1x$wyjS7I!;igZc%Sk<;e8Uu@jdSc-jnbMO&vGonz%vG@}7?y12;g& zycNjD?#|$r*mrUB_(t6Jd#Lwt?_u7Xy%%_o^d8|o%6qi;eeZ|fThvABX3AH))gHCi z`<3@=#Scx~TwUV*MtSNM>XzzO_~6E^)ot+o!rQ6at2?MWsypF*V19Ti@P6j~T-{ae zQ+HE$SNBl&RQFPss{QIRh2LXV2k>K(m#cB_f4xtujLNDBl~a@IkUFfcP)F32_}P&A z;FDi}p#ISNs`oW@Kb2QgYFZWWmBbl!R2@?#b(K1Kb)YUF-eA`=$4F?;Glrx=!6+JwQEBJxD!RJw%0SN!9SyXrxxus#;TZb-g;R8mg&U z-dk0y+Uf?Cc;EECr8=ssdfrRa8MUs?stt9cdZ>DsdboOodZc=kdbE0sdaQb!dc5}; z?W|bDz0Z4J@V@AM+54<|l6tawih8PgntHnWV|+XC8R}2fGu5A|KUaUDo~8a$ z{gwJ_^=$PV^<4El^*8GI>ILeB>P70s>TlIc)ZeMUS1(mBQ!iKlpkAR~sa~aCtzM&E zt6ryGuil{EsNSUBto~8GMZHzMO}$;cL%mb|llo`%FW$4&yVSeYd(^+G_u^OE->2TM zKA=9RKBPXZKB7LVKBoR%eO!G)eNuf&eOi4+eO7%=eO`S*eNlZ${fGLp`ilCh`kMN> z`iA z{RXb8wAMrTgvp4;x1{t%`exeKyY(KuSO1>ASl?VV5id`tJH3_-f?6^rd>gz6?L6H>MBhgZgqkt}{BTCv;9v>O=al zzCs_-SL%D~`{?^>{6>_%pU&$kJ*^A6sAu$1eN311Rr9d~7L9hS%_CwA95OR5XgUF`8W^OFtG5hW?V!Ul)OuETwg6b?GWyzkc^sDcs%H zr^iCe#39=r-g9~to2#t`3c-49bT+JE!*#S_8arglw$r1tB7%l#hG)Uwa07ov%QCCg zH!C+OvvP+<%QCAaf@_8C7;B`sy%r4>TdPCZYS}es*^4cEbHZM1n!R&tz1C`&^qP&Z z*WDZUpN&=obJB--(y}&rc(fvz6KNJ?Y{xXa7gCYz?xe>;^&zXOLldJ_ncOwaaFq(` zQbCKNAZ&6`L5r3Htfh^D7KMYJX+{kQ{QW(wt3r% zMPw&!zm-<@kiC95C*!V=NRYL7vPY(+|A^qtPFXlpwtw2fo3?PKKM zaH;0fa;Q)Abh)Rmt;5(21$w?dR9TBh7V4|baHtygc3EnM=GW>&)A%>vsSBF?kv)Xx zD7x4VbmxA!DTqB$A4eB~5MiJEn4??u;Ux?oStWBL*v;*RyDY5X8*yQX z7qPAdYXmlO+OXCztO=1*)4J8uXY0FS;cqBei$}4a+6*%zrWxvjM~i=`4gRo`Gz4-+ zuoztp_YkZj>*6hB?y)dMYxbf!@y%p&C}d2FZA}!$M-91|ix!1tvGIw5WTA;dZWuIV zM$LS8?XZE7vzaV6F8#T2i3YiGnVTCI`_7GvzvRZnUvlGazW7aUT12{z=Qf&3L&< zi+|GMxA8eQY4J~5{F4^{q{TmJ@lRU(M=XAu7jk(!KX2z3?Dc}BuVDEvSo|}V-Wj2H z(#HRy$Tw3E|3Yi{Kx_CwYv!Xh_|O`9G6k_`v<5#~Lw}|q_KDWu%Z`iRpw0Lz_0=A3 zA%~qcx)!=7_ukM$j$plqJBV4pbxM(f@DT{wf z@Mk30WHSeTh>fTHf>2qgJoN$WZCjW z%Y&@gjtAL^5yw#zN6Gb6C$t^k)Qy$Yaoq;(OLNoj(@RswZA`aLm3)a`nyC5m@mkRP z*V^X*ASI_s@9XV-qA=~V&mPuZd(CSfMJS3=jW?^JjE!x)?2FfY@RFkZrV*u$D@I1g z6sJ$ti|+qr4BQ&GeN_gT$^|4*L|pdYhtDeT3`Qy*qB2yl_FW;QlrEU9$K3+xGn3E43dg zO6@Nd<%xgZw|j@)7QCfCg-@DLP^e&f|C@PiWAMUZ7 zz0e1kEW!2JqIbC^d5z!IBUFO-o0MWDr4;d{Nx&Q%-VpYE_&f$upKBS(;O%KaY z@t)En(2uH=08aGpi%RhY%r7N>0qlE5b>(hFdH1C`(AuM^l&Hm|rd}n+r z_$(YFj|JCqFfhk3{}b!Ru$cF0T_e|&`yt$?e&&4^_Lmzg>Y3$ceZFRt|GVRvH@?EX zPVMB@=Mw8j{qc303)MB+DjXY+iS9)mf*;o@Y!}~YznS!t*8*#jD>J^E<ejp2wj z=62CO?MogLK6zaDR70}d9G^)`XdL`9#>Lm^K6({g%Z-=HjCt}}p3YGO={Lig za1VVGKA1ScbpZ$S(}ZR2cL98IW%KHrF#la}HOE&}t0+acO1PVS(S0-?YCkt;*% z(Hyt=X^fld7QS+A7%->bbe-4AXph@8z7s6znvyZ(5y&6(o#d6m7tKwaxbQu~ON=K& zZJ2wQKIIE-;5*gj7y8JJ&43k^n|+$=Mf2l&xK_MG!i38T?lIdl@s;OA_tA^$QD68@ z<%Ap5HuXd0Ov^ED6E?g)sAs~4KB*4w@$kAB_wxN{+ngWO!#|P@>D4GDPc?#HkT~(% zs#fFkZu}MFQ&H{`E5%Xqn0P{bU2Raesyo&F>S6V6^)dCN`UUm0`W^NEQs1?NEDu>8 zwtUg@ch;+|k6ZuP`nT4PV5)l}Ei*c9+Nea*g*Z@@R=oAe#_ z9rOK}-|Y_sYQjH#uIK&5?EA@vM!7+^BQOlRCiuHu`MeFyiKd}DF7=bl6f`%r)ui96K5%e1)xZC%P-^C+1 zTQGu`FoM_KKaCNH3;%TCtqb42@alzEE;*0xjpXd^mR1&OKn}u>!hb?hji2Uc;nl+L@=oY1&{v8Tn^K}IP)e0DrCg~{DwQgzUv{NN zaX@o)DlWyX)F~dNUTFX}HYr}E85rPK0!mP6QCgLd5?0!jcBMn$_`BDxbg|*LFJRmr?Ye&nYh`f2_Qyyrg_ZnO454ysW&Ud`lz*{dAkPenY1&+C;t#XZXN$~TmIlwHaJ zEW>iXdV?~h#+9AQy~_Q{XM{u4svT;l+M{afLbXfzQ`Gsk=vVvHHEKfbmF+3Fsf*Mo zz8_N_R_;?CQ65qrQ%)$4D~~EqDruB|S~;owk@7j^*J7i%N;xRDifv-May$CGQf$I? z*2Mw&Tlnv3%>ImM6cO>Tcv<{VRn->sw@kePG~$r@jQTQmrE00SEU{c~x!ZEu@^i~? ztyXKjwadE9dYAS6qMD+WMTd*hMPDs?tLV4I)y0j)i;KsL_Z8n;{B-f##lN&gY};(l z*j}}rvHh&1yrjEiqU4s62TGnUd8y>hlJAzhyTH3(*@9aZoLq2b!E9+?>BiDSrC%;R zU79KVO<8r>lCnKz50|}I_HNln<=*mG`Ns0e@(0SFspzg)T=CtCY-Mp}N9CT%M=QTy zd9JFYYP{;!s-IMsR(DhnR4=Q3vHBa;XYE$IX5VkW-TsXI8}_&DKeK0RifdYGVl^W* z8*3h|dAjD=npbPSRrA+1KX6zb)s99-na;0KI(kh`Ks)o-x;1sR#G+f!Rui#+ueQO*HLqx~1vfrjt!?H+{e9-KMim=e&xy z+*{{u@y5I(-YdLUdiQw`d++u>?0w4nW$(-0)835tjQ2fnwz<1`y!nadSDU}z{BHBv z=5s#9m+R2j2_+yrrbY+tSx^Ma%Uq>6Wjy z{GjERt!it1>zdZd)^zLlTmP~3=dHgDSwq#K#!y@6aOkDb_rmqzjo~N4FSRLczP2T8 z*R&mPd%o@G?Y{Ok?RU4o)_%65vZJr#K*z%!uXlXZS<+eC>FbPi_H~YTp6L8A;)(ENs7+E;7@bJQKEd0xbXBM98igoSldbsPWUEg1%E~;PDw@6>~^r9CR zebimsy`=l@?x(un?0&aL>8bD0damp_-1AJ&cYFR(vuX)#n>MMP&|cL3Qu~#bjfSF| zqYp&C9{p`>N$ha!SnS2v`*CZ0aeRGzB7RFe9sg?l?f7pKrHSsu&cxxw$;5XPXA{}p z`d+Q~^4>$ePxpSK_rt!nzRUZz_3i09+4p?kd;K;2-Tj;UALu{b|C538fx3Z~f$o8^ zfo%f^25uiXKJe**X9ivxczxh!1G9r2gNFuB4t{U&SBpy*cPzeQ@#Nxr7k_#2+l${_ z{LhPjzIb-1WXLt-9a=WDdT8U&twYC#P7IwKdVc8jq3;g;UZjTe0|P@vAVx{X&b{{q}Iw9`uU^XTS3u_386_{3N(p73D&o1y18*W2OBTgrp>U|UNd)6b5!Jk^v$nEGjU_Z!ZE?VI_M(`NxPqOXLD!;q ztUDt<|44M#RsHT@XGhSL8C*X&xZZO1e_ml-^HH7U?D^-rlFd#>L!zytPgMsyHErDy zXJlQXb13L>HEG$OQ}sb&5t5JpmBk0%>`;^%&1I_;RU#OQ$EuC)lWT^B>M1MNHQ9@A zxOMzYa(E^aI=|Iy=fZ^xS#d)A#^S3EE2X3{R2PHa8|_n^u5 z7z;bS764GSIfL;~I3BHax#L}ycr2;*I*XmP&BB?8$1<6H*QBN*ONN^L1EX!3{S&F> z1Lm((DwDGK4mOM)-qQF^WmDI(j^JRp-gX0(EF378MJ)p;((OG1foK27-aVj5*%fOH z7^s6JeOHIneu9MBN1#?LR6{)tShPWM0Z$j2%UN4&a|0qaj5}Ou2?n~>;%~*1NE@yuLaJ)j+V_mv99diX)s<p5j z>Uxh5$<`1M#u=<{6DPE4cPvorZ4ZQ!!>uFxhW)?+k}5Bp6cM!J!7hj;EyE(}#N6z) zu3kW)%Nln#^)$FNy(`h*scWu=o+h_ip{?)ktS7I|T#mpWB|W z*H&79z;Rb1ZjXfsue??fF{9mn=BlbG)e;&zOPuo(Z;aYAUF_71G_ zf30MyZM0|3KQHG5DeD~cJ7Brp@AQjv*>Z70mt&*%4E}72vRFtW!FyA_3Lel&+rE&yN`Ul5w#LJ5v#~lz~doB(PUpNzn@2^SSV=*cTG#d@Cka_|~rI zUeTN_KP^U1pU$2>Eski*Zr`%y_GQ|&&so&*JCC#PUQs>RJp|)zF4JkllK*a3~1p`f>46#AiguUAe4 z?!q=r3<_th7lla`SG&NsB<&a!uEel#R;m`_RbC72K5V-Ke{st#e{tZ?{zQ!SO%JbY zui8JMTk703t`fD_+jrfX#rp?8v2D6vce;u_d!Fly2y2<6Dp0-mt2?!wU)_6nWA+z) zqoTfVBs#Hww%Tqlu~(GOI^14++2*^3wOuc(o{CDnxVllCi}W?tc}q*eLk9ea*Djzv z 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 literal 0 HcmV?d00001 diff --git a/media/baseset/OpenTTD-Serif.ttf b/media/baseset/OpenTTD-Serif.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5a139b99f1cd6e58d9527d9786252ca50387c233 GIT binary patch literal 77168 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

EPe;^yje?^0$ulSI4o6z-4#rMD5S{HAPdntnc(1 zhuf+u4dXgbe{WmWyFd4{s5I=|pWx%Rwb5U}SAMQ3313u!&d&|O1F4+XD|H`nQuKJ7 zTe^9&lTE5!(?`daCOOuGdqJP%vT!e~3gYOFcx@OzEU3xFnJpYmHsDyD69*mCayS~7 zrq8SVLH$AbM~7x<&+?)d<(uZUJLbeU1UMugQ}>?NUXzy9+9eHAnf(3d(d?7 zd#|kAaQ1;!g^UG-X2e#-H3hK#XMCb69jPO4EW5j}F+00u_r2IOCM-ja+H2qkCHOL# z1VmK*MgSg?h17si#V@QA>#tYSb~;Usc!;6_yq2DH5Hg1nylspb(Ruiq@rb;9&0 zn}xqPx)rR=OdoU)(};1l{*s&otu{u_3epQ=rs_mCc1DVfV}AI} zjh}p-oJZpfE|Qc~t(_{2G4(7iH1>{)SRB1W|l)`?+~F z`Kze%39N5*Y@QK-K&3J|<*?)M80Ea-2r`cHdQ#TaTfibvn{Xb2@WB-bd(u^s78vo4P zjunTWR8B}bp&DtfvRQjBUismkS(d`4_7xrWfv4)iE$Qi&DN|6pFwL4}4j=s|^{nLn zlghqbgHKNTEP1a%>F)C~R3k+UA_D@NJb6(e8uaRs?>;Yo`n}!xYKau?V)ax=3CpaMcAR|n6W@5v{n3atUkk*W{Qi@`I^3u)$=gq*L9zrk5Ov}sA7RQqR6n#u*2VVl$fEwxgF969X#$_@Gd;Bo1Zn zqxZm?&o2O$i^>EjM+`_bd94-hXoRe6&{nd3$a+0n%Vnop3l+M6pE6hC0(#}_yxZ~P z?bgxNC@vemF0a11P8}Kj7D+k2gG@<%09-qY|3k^ɷ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 PqZAQOdFL-%{^b7vg((OX literal 0 HcmV?d00001 diff --git a/media/baseset/OpenTTD-Small.ttf b/media/baseset/OpenTTD-Small.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5e702c1850a51aae2215e6ea41b43590f01146ca GIT binary patch literal 56264 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�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 e$=;^g)WrV&)B0weGGG7vBYlHasParent()) delete fc; + if (GetFontCacheSubSetting(fs)->font.empty()) { + TryLoadDefaultTrueTypeFont(fs); + } else { #ifdef WITH_FREETYPE - LoadFreeTypeFont(fs); + LoadFreeTypeFont(fs); #elif defined(_WIN32) - LoadWin32Font(fs); + LoadWin32Font(fs); #elif defined(WITH_COCOA) - LoadCoreTextFont(fs); + LoadCoreTextFont(fs); #endif + } } } diff --git a/src/fontcache/freetypefontcache.cpp b/src/fontcache/freetypefontcache.cpp index eca647d9c8..bcbfbc2a52 100644 --- a/src/fontcache/freetypefontcache.cpp +++ b/src/fontcache/freetypefontcache.cpp @@ -115,6 +115,42 @@ void FreeTypeFontCache::SetFontSize(FontSize, FT_Face, int pixels) } } +static FT_Error LoadFont(FontSize fs, FT_Face face, const char *font_name, uint size) +{ + Debug(fontcache, 2, "Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name); + + /* Attempt to select the unicode character map */ + FT_Error error = FT_Select_Charmap(face, ft_encoding_unicode); + if (error == FT_Err_Ok) goto found_face; // Success + + if (error == FT_Err_Invalid_CharMap_Handle) { + /* Try to pick a different character map instead. We default to + * the first map, but platform_id 0 encoding_id 0 should also + * be unicode (strange system...) */ + FT_CharMap found = face->charmaps[0]; + int i; + + for (i = 0; i < face->num_charmaps; i++) { + FT_CharMap charmap = face->charmaps[i]; + if (charmap->platform_id == 0 && charmap->encoding_id == 0) { + found = charmap; + } + } + + if (found != nullptr) { + error = FT_Set_Charmap(face, found); + if (error == FT_Err_Ok) goto found_face; + } + } + + FT_Done_Face(face); + return error; + +found_face: + new FreeTypeFontCache(fs, face, size); + return FT_Err_Ok; +} + /** * Loads the freetype font. * First type to load the fontname as if it were a path. If that fails, @@ -157,40 +193,40 @@ void LoadFreeTypeFont(FontSize fs) if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, &face); if (error == FT_Err_Ok) { - Debug(fontcache, 2, "Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name); - - /* Attempt to select the unicode character map */ - error = FT_Select_Charmap(face, ft_encoding_unicode); - if (error == FT_Err_Ok) goto found_face; // Success - - if (error == FT_Err_Invalid_CharMap_Handle) { - /* Try to pick a different character map instead. We default to - * the first map, but platform_id 0 encoding_id 0 should also - * be unicode (strange system...) */ - FT_CharMap found = face->charmaps[0]; - int i; - - for (i = 0; i < face->num_charmaps; i++) { - FT_CharMap charmap = face->charmaps[i]; - if (charmap->platform_id == 0 && charmap->encoding_id == 0) { - found = charmap; - } - } - - if (found != nullptr) { - error = FT_Set_Charmap(face, found); - if (error == FT_Err_Ok) goto found_face; - } + error = LoadFont(fs, face, font_name, settings->size); + if (error != FT_Err_Ok) { + ShowInfo("Unable to use '{}' for {} font, FreeType reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), error); } + } else { + FT_Done_Face(face); } +} - FT_Done_Face(face); +/** + * Load a TrueType font from a file. + * @param fs The font size to load. + * @param file_name Path to the font file. + * @param size Requested font size. + */ +void LoadFreeTypeFont(FontSize fs, const std::string &file_name, uint size) +{ + if (_library == nullptr) { + if (FT_Init_FreeType(&_library) != FT_Err_Ok) { + ShowInfo("Unable to initialize FreeType, using sprite fonts instead"); + return; + } - ShowInfo("Unable to use '{}' for {} font, FreeType reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), error); - return; + Debug(fontcache, 2, "Initialized"); + } -found_face: - new FreeTypeFontCache(fs, face, settings->size); + FT_Face face = nullptr; + int32_t index = 0; + FT_Error error = FT_New_Face(_library, file_name.c_str(), index, &face); + if (error == FT_Err_Ok) { + LoadFont(fs, face, file_name.c_str(), size); + } else { + FT_Done_Face(face); + } } diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index d76fb0ef5c..2b5f0e14b1 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -298,6 +298,40 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa) return new_glyph.sprite; } +static CTFontDescriptorRef LoadFontFromFile(const std::string &font_name) +{ + if (!MacOSVersionIsAtLeast(10, 6, 0)) return nullptr; + + /* Might be a font file name, try load it. Direct font loading is + * only supported starting on OSX 10.6. */ + CFAutoRelease path; + + /* See if this is an absolute path. */ + if (FileExists(font_name)) { + path.reset(CFStringCreateWithCString(kCFAllocatorDefault, font_name.c_str(), kCFStringEncodingUTF8)); + } else { + /* Scan the search-paths to see if it can be found. */ + std::string full_font = FioFindFullPath(BASE_DIR, font_name); + if (!full_font.empty()) { + path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8)); + } + } + + if (path) { + /* Try getting a font descriptor to see if the system can use it. */ + CFAutoRelease url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(), kCFURLPOSIXPathStyle, false)); + CFAutoRelease descs(CTFontManagerCreateFontDescriptorsFromURL(url.get())); + + if (descs && CFArrayGetCount(descs.get()) > 0) { + CTFontDescriptorRef font_ref = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0); + CFRetain(font_ref); + return font_ref; + } + } + + return nullptr; +} + /** * Loads the TrueType font. * If a CoreText font description is present, e.g. from the automatic font @@ -318,33 +352,9 @@ void LoadCoreTextFont(FontSize fs) } if (!font_ref && MacOSVersionIsAtLeast(10, 6, 0)) { - /* Might be a font file name, try load it. Direct font loading is - * only supported starting on OSX 10.6. */ - CFAutoRelease path; - - /* See if this is an absolute path. */ - if (FileExists(settings->font)) { - path.reset(CFStringCreateWithCString(kCFAllocatorDefault, settings->font.c_str(), kCFStringEncodingUTF8)); - } else { - /* Scan the search-paths to see if it can be found. */ - std::string full_font = FioFindFullPath(BASE_DIR, settings->font); - if (!full_font.empty()) { - path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8)); - } - } - - if (path) { - /* Try getting a font descriptor to see if the system can use it. */ - CFAutoRelease url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(), kCFURLPOSIXPathStyle, false)); - CFAutoRelease descs(CTFontManagerCreateFontDescriptorsFromURL(url.get())); - - if (descs && CFArrayGetCount(descs.get()) > 0) { - font_ref.reset((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0)); - CFRetain(font_ref.get()); - } else { - ShowInfo("Unable to load file '{}' for {} font, using default OS font selection instead", settings->font, FontSizeToName(fs)); - } - } + /* Might be a font file name, try load it. */ + font_ref.reset(LoadFontFromFile(settings->font)); + if (!font_ref) ShowInfo("Unable to load file '{}' for {} font, using default OS font selection instead", settings->font, FontSizeToName(fs)); } if (!font_ref) { @@ -372,3 +382,17 @@ void LoadCoreTextFont(FontSize fs) new CoreTextFontCache(fs, std::move(font_ref), settings->size); } + +/** + * Load a TrueType font from a file. + * @param fs The font size to load. + * @param file_name Path to the font file. + * @param size Requested font size. + */ +void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size) +{ + CFAutoRelease font_ref{LoadFontFromFile(file_name)}; + if (font_ref) { + new CoreTextFontCache(fs, std::move(font_ref), size); + } +} diff --git a/src/os/macosx/font_osx.h b/src/os/macosx/font_osx.h index 56d488771a..ca2ac1d5e9 100644 --- a/src/os/macosx/font_osx.h +++ b/src/os/macosx/font_osx.h @@ -36,5 +36,6 @@ public: }; void LoadCoreTextFont(FontSize fs); +void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size); #endif /* FONT_OSX_H */ diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 3602c11876..1dc1977b37 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -317,6 +317,66 @@ void Win32FontCache::ClearFontCache() } +static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont) +{ + wchar_t fontPath[MAX_PATH] = {}; + + /* See if this is an absolute path. */ + if (FileExists(font_name)) { + convert_to_fs(font_name, fontPath, lengthof(fontPath)); + } else { + /* Scan the search-paths to see if it can be found. */ + std::string full_font = FioFindFullPath(BASE_DIR, font_name); + if (!full_font.empty()) { + convert_to_fs(font_name, fontPath, lengthof(fontPath)); + } + } + + if (fontPath[0] != 0) { + if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { + /* Try a nice little undocumented function first for getting the internal font name. + * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ + static LibraryLoader _gdi32("gdi32.dll"); + typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); + static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetFunction("GetFontResourceInfoW"); + + if (GetFontResourceInfo != nullptr) { + /* Try to query an array of LOGFONTs that describe the file. */ + DWORD len = 0; + if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) { + LOGFONT *buf = (LOGFONT *)new byte[len]; + if (GetFontResourceInfo(fontPath, &len, buf, 2)) { + logfont = *buf; // Just use first entry. + } + delete[](byte *)buf; + } + } + + /* No dice yet. Use the file name as the font face name, hoping it matches. */ + if (logfont.lfFaceName[0] == 0) { + wchar_t fname[_MAX_FNAME]; + _wsplitpath(fontPath, nullptr, nullptr, fname, nullptr); + + wcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE); + logfont.lfWeight = strcasestr(font_name.c_str(), " bold") != nullptr || strcasestr(font_name.c_str(), "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. + } + } + } + + return logfont.lfFaceName[0] != 0; +} + +static void LoadWin32Font(FontSize fs, const LOGFONT &logfont, uint size, const char *font_name) +{ + HFONT font = CreateFontIndirect(&logfont); + if (font == nullptr) { + ShowInfo("Unable to use '{}' for {} font, Win32 reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), GetLastError()); + return; + } + DeleteObject(font); + + new Win32FontCache(fs, logfont, size); +} /** * Loads the GDI font. * If a GDI font description is present, e.g. from the automatic font @@ -341,51 +401,8 @@ void LoadWin32Font(FontSize fs) logfont = *(const LOGFONT *)settings->os_handle; } else if (strchr(font_name, '.') != nullptr) { /* Might be a font file name, try load it. */ - - wchar_t fontPath[MAX_PATH] = {}; - - /* See if this is an absolute path. */ - if (FileExists(settings->font)) { - convert_to_fs(font_name, fontPath, lengthof(fontPath)); - } else { - /* Scan the search-paths to see if it can be found. */ - std::string full_font = FioFindFullPath(BASE_DIR, font_name); - if (!full_font.empty()) { - convert_to_fs(font_name, fontPath, lengthof(fontPath)); - } - } - - if (fontPath[0] != 0) { - if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { - /* Try a nice little undocumented function first for getting the internal font name. - * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ - static LibraryLoader _gdi32("gdi32.dll"); - typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); - static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetFunction("GetFontResourceInfoW"); - - if (GetFontResourceInfo != nullptr) { - /* Try to query an array of LOGFONTs that describe the file. */ - DWORD len = 0; - if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) { - LOGFONT *buf = (LOGFONT *)new byte[len]; - if (GetFontResourceInfo(fontPath, &len, buf, 2)) { - logfont = *buf; // Just use first entry. - } - delete[] (byte *)buf; - } - } - - /* No dice yet. Use the file name as the font face name, hoping it matches. */ - if (logfont.lfFaceName[0] == 0) { - wchar_t fname[_MAX_FNAME]; - _wsplitpath(fontPath, nullptr, nullptr, fname, nullptr); - - wcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE); - logfont.lfWeight = strcasestr(font_name, " bold") != nullptr || strcasestr(font_name, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. - } - } else { - ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font_name, FontSizeToName(fs)); - } + if (!TryLoadFontFromFile(settings->font, logfont)) { + ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font_name, FontSizeToName(fs)); } } @@ -394,12 +411,25 @@ void LoadWin32Font(FontSize fs) convert_to_fs(font_name, logfont.lfFaceName, lengthof(logfont.lfFaceName)); } - HFONT font = CreateFontIndirect(&logfont); - if (font == nullptr) { - ShowInfo("Unable to use '{}' for {} font, Win32 reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), GetLastError()); - return; - } - DeleteObject(font); + LoadWin32Font(fs, logfont, settings->size, font_name); +} + +/** + * Load a TrueType font from a file. + * @param fs The font size to load. + * @param file_name Path to the font file. + * @param size Requested font size. + */ +void LoadWin32Font(FontSize fs, const std::string &file_name, uint size) +{ + LOGFONT logfont; + MemSetT(&logfont, 0); + logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH; + logfont.lfCharSet = DEFAULT_CHARSET; + logfont.lfOutPrecision = OUT_OUTLINE_PRECIS; + logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - new Win32FontCache(fs, logfont, settings->size); + if (TryLoadFontFromFile(file_name, logfont)) { + LoadWin32Font(fs, logfont, size, file_name.c_str()); + } } diff --git a/src/os/windows/font_win32.h b/src/os/windows/font_win32.h index 48459543fd..bdb2cc9a9b 100644 --- a/src/os/windows/font_win32.h +++ b/src/os/windows/font_win32.h @@ -41,5 +41,6 @@ public: }; void LoadWin32Font(FontSize fs); +void LoadWin32Font(FontSize fs, const std::string &file_name, uint size); #endif /* FONT_WIN32_H */ From 20f1a0dc5711b184e48d3ebb22f98110f92d1133 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Dec 2023 02:30:12 +0100 Subject: [PATCH 09/14] Fix: [OSX] Spurious log message when a sprite glyph was layouted. --- src/os/macosx/string_osx.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 3c96bababb..55927b161e 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -168,6 +168,9 @@ static CTRunDelegateCallbacks _sprite_font_callback = { CFAutoRelease base(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull)); CFAttributedStringReplaceString(str.get(), CFRangeMake(0, 0), base.get()); + const UniChar replacment_char = 0xFFFC; + CFAutoRelease replacment_str(CFStringCreateWithCharacters(kCFAllocatorDefault, &replacment_char, 1)); + /* Apply font and colour ranges to our string. This is important to make sure * that we get proper glyph boundaries on style changes. */ int last = 0; @@ -193,6 +196,8 @@ static CTRunDelegateCallbacks _sprite_font_callback = { for (ssize_t c = last; c < i.first; c++) { if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END && i.second->fc->MapCharToGlyph(buff[c], false) == 0) { CFAutoRelease del(CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24)))); + /* According to the offical documentation, if a run delegate is used, the char should always be 0xFFFC. */ + CFAttributedStringReplaceString(str.get(), CFRangeMake(c, 1), replacment_str.get()); CFAttributedStringSetAttribute(str.get(), CFRangeMake(c, 1), kCTRunDelegateAttributeName, del.get()); } } @@ -242,7 +247,8 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font CGGlyph gl[this->glyphs.size()]; CTRunGetGlyphs(run, CFRangeMake(0, 0), gl); for (size_t i = 0; i < this->glyphs.size(); i++) { - if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && gl[i] == 0) { + if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && (gl[i] == 0 || gl[i] == 3)) { + /* A glyph of 0 indidicates not found, while apparently 3 is what char 0xFFFC maps to. */ this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]); this->positions[i * 2 + 0] = pts[i].x; this->positions[i * 2 + 1] = (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2; // Align sprite font to centre From e1f5be62447a257310ea07d325843f35cf0d81bc Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 16 Dec 2023 18:28:49 +0100 Subject: [PATCH 10/14] Add: GUI options to select sprite font and AA mode for all fonts. --- src/fontcache.cpp | 4 +-- src/fontcache.h | 2 ++ src/lang/english.txt | 5 ++++ src/settings_gui.cpp | 43 ++++++++++++++++++++++++++++ src/table/settings/misc_settings.ini | 12 ++++++++ src/widgets/settings_widget.h | 2 ++ 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 42643bbff7..2a5772fc3b 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -96,7 +96,7 @@ bool GetFontAAState(FontSize size, bool check_blitter) /* AA is only supported for 32 bpp */ if (check_blitter && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return false; - return GetFontCacheSubSetting(size)->aa; + return _fcsettings.global_aa || GetFontCacheSubSetting(size)->aa; } void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa) @@ -204,7 +204,7 @@ void InitFontCache(bool monospace) FontCache *fc = FontCache::Get(fs); if (fc->HasParent()) delete fc; - if (GetFontCacheSubSetting(fs)->font.empty()) { + if (!_fcsettings.prefer_sprite && GetFontCacheSubSetting(fs)->font.empty()) { TryLoadDefaultTrueTypeFont(fs); } else { #ifdef WITH_FREETYPE diff --git a/src/fontcache.h b/src/fontcache.h index 73963011b5..9ba6055504 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -218,6 +218,8 @@ struct FontCacheSettings { FontCacheSubSetting medium; ///< The normal font size. FontCacheSubSetting large; ///< The largest font; mostly used for newspapers. FontCacheSubSetting mono; ///< The mono space font used for license/readme viewers. + bool prefer_sprite; ///< Whether to prefer the built-in sprite font over resizable fonts. + bool global_aa; ///< Whether to anti alias all font sizes. }; extern FontCacheSettings _fcsettings; diff --git a/src/lang/english.txt b/src/lang/english.txt index 05e58029a0..17eafcb7cc 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1044,6 +1044,11 @@ STR_GAME_OPTIONS_GUI_SCALE_AUTO_TOOLTIP :{BLACK}Check th STR_GAME_OPTIONS_GUI_SCALE_BEVELS :{BLACK}Scale bevels STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP :{BLACK}Check this box to scale bevels by interface size +STR_GAME_OPTIONS_GUI_FONT_SPRITE :{BLACK}Use traditional sprite font +STR_GAME_OPTIONS_GUI_FONT_SPRITE_TOOLTIP :{BLACK}Check this box if you prefer to use the tradition fixed-size sprite font. +STR_GAME_OPTIONS_GUI_FONT_AA :{BLACK}Anti-alias fonts +STR_GAME_OPTIONS_GUI_FONT_AA_TOOLTIP :{BLACK}Check this box to anti-alias resizable fonts. + STR_GAME_OPTIONS_GUI_SCALE_1X :1x STR_GAME_OPTIONS_GUI_SCALE_2X :2x STR_GAME_OPTIONS_GUI_SCALE_3X :3x diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 07bd14b087..f4ec1ba298 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -50,6 +50,10 @@ #include "safeguards.h" +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) +# define HAS_TRUETYPE_FONT +#endif + static const StringID _autosave_dropdown[] = { STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF, STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_10_MINUTES, @@ -559,6 +563,30 @@ struct GameOptionsWindow : Window { break; } +#ifdef HAS_TRUETYPE_FONT + case WID_GO_GUI_FONT_SPRITE: + _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite; + + this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite); + this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite); + this->SetDirty(); + + InitFontCache(false); + InitFontCache(true); + SetupWidgetDimensions(); + ReInitAllWindows(true); + break; + + case WID_GO_GUI_FONT_AA: + _fcsettings.global_aa = !_fcsettings.global_aa; + + this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa); + this->SetDirty(); + + ClearFontCache(); + break; +#endif /* HAS_TRUETYPE_FONT */ + case WID_GO_GUI_SCALE: if (ClickSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, this->gui_scale)) { if (!_ctrl_pressed) this->gui_scale = ((this->gui_scale + 12) / 25) * 25; @@ -750,6 +778,11 @@ struct GameOptionsWindow : Window { this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, _gui_scale_cfg == -1); this->SetWidgetLoweredState(WID_GO_GUI_SCALE_BEVEL_BUTTON, _settings_client.gui.scale_bevels); +#ifdef HAS_TRUETYPE_FONT + this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite); + this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa); + this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite); +#endif /* HAS_TRUETYPE_FONT */ this->SetWidgetDisabledState(WID_GO_BASE_GRF_DROPDOWN, _game_mode != GM_MENU); this->SetWidgetDisabledState(WID_GO_BASE_SFX_DROPDOWN, _game_mode != GM_MENU); @@ -823,6 +856,16 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, STR_NULL), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_BEVEL_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP), EndContainer(), +#ifdef HAS_TRUETYPE_FONT + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_FONT_SPRITE, STR_NULL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_SPRITE), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_FONT_SPRITE_TOOLTIP), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), + NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_FONT_AA, STR_NULL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_AA), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_FONT_AA_TOOLTIP), + EndContainer(), +#endif /* HAS_TRUETYPE_FONT */ EndContainer(), EndContainer(), diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 7e9db80c83..9158082f2d 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -258,6 +258,18 @@ name = ""mono_aa"" var = _fcsettings.mono.aa def = false +[SDTG_BOOL] +ifdef = HAS_TRUETYPE_FONT +name = ""global_aa"" +var = _fcsettings.global_aa +def = true + +[SDTG_BOOL] +ifdef = HAS_TRUETYPE_FONT +name = ""prefer_sprite_font"" +var = _fcsettings.prefer_sprite +def = false + [SDTG_VAR] name = ""sprite_cache_size_px"" type = SLE_UINT diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index b59778a14d..4c40f1e0a0 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -25,6 +25,8 @@ enum GameOptionsWidgets : WidgetID { WID_GO_GUI_SCALE, ///< GUI Scale slider. WID_GO_GUI_SCALE_AUTO, ///< Autodetect GUI scale button. WID_GO_GUI_SCALE_BEVEL_BUTTON, ///< Toggle for chunky bevels. + WID_GO_GUI_FONT_SPRITE, ///< Toggle whether to prefer the sprite font over TTF fonts. + WID_GO_GUI_FONT_AA, ///< Toggle whether to anti-alias fonts. WID_GO_BASE_GRF_DROPDOWN, ///< Use to select a base GRF. WID_GO_BASE_GRF_PARAMETERS, ///< Base GRF parameters. WID_GO_BASE_GRF_OPEN_URL, ///< Open base GRF URL. From 994bdff81e4951ba47649224564a73ee248f44c5 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 17 Dec 2023 22:13:49 +0100 Subject: [PATCH 11/14] Codechange: [CMake] Use timestamps to copy non-generated baseset files. --- media/baseset/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/baseset/CMakeLists.txt b/media/baseset/CMakeLists.txt index b92eb0f648..4e1dd26d74 100644 --- a/media/baseset/CMakeLists.txt +++ b/media/baseset/CMakeLists.txt @@ -67,7 +67,7 @@ foreach(BASESET_OTHER_SOURCE_FILE IN LISTS BASESET_OTHER_SOURCE_FILES) get_filename_component(BASESET_OTHER_SOURCE_FILE_NAME "${BASESET_OTHER_SOURCE_FILE}" NAME) set(BASESET_OTHER_BINARY_FILE "${CMAKE_BINARY_DIR}/baseset/${BASESET_OTHER_SOURCE_FILE_NAME}") - add_custom_command(OUTPUT ${BASESET_OTHER_BINARY_FILE} + add_custom_command_timestamp(OUTPUT ${BASESET_OTHER_BINARY_FILE} COMMAND ${CMAKE_COMMAND} -E copy ${BASESET_OTHER_SOURCE_FILE} ${BASESET_OTHER_BINARY_FILE} From 302ba934716b1de58138fb0def791ef60012dff0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 14 Jan 2024 23:25:54 +0100 Subject: [PATCH 12/14] Fix: [SDL2] only resolutions of the first display were shown (#11778) --- src/gfx.cpp | 4 ++++ src/video/sdl2_v.cpp | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 64b10844b8..3953e7497e 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1779,6 +1779,10 @@ bool ToggleFullScreen(bool fs) void SortResolutions() { std::sort(_resolutions.begin(), _resolutions.end()); + + /* Remove any duplicates from the list. */ + auto last = std::unique(_resolutions.begin(), _resolutions.end()); + _resolutions.erase(last, _resolutions.end()); } /** diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 183b8354c1..41fc5e99ec 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -59,13 +59,15 @@ static void FindResolutions() { _resolutions.clear(); - for (int i = 0; i < SDL_GetNumDisplayModes(0); i++) { - SDL_DisplayMode mode; - SDL_GetDisplayMode(0, i, &mode); - - if (mode.w < 640 || mode.h < 480) continue; - if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(mode.w, mode.h)) != _resolutions.end()) continue; - _resolutions.emplace_back(mode.w, mode.h); + for (int display = 0; display < SDL_GetNumVideoDisplays(); display++) { + for (int i = 0; i < SDL_GetNumDisplayModes(display); i++) { + SDL_DisplayMode mode; + SDL_GetDisplayMode(display, i, &mode); + + if (mode.w < 640 || mode.h < 480) continue; + if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(mode.w, mode.h)) != _resolutions.end()) continue; + _resolutions.emplace_back(mode.w, mode.h); + } } /* We have found no resolutions, show the default list */ From 32fc740582a7f113f549784fbbe7253557fe91e8 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 14 Jan 2024 23:41:51 +0100 Subject: [PATCH 13/14] Fix: [SDL2] fullscreen always used the resolution of the first display (#11779) --- src/video/sdl2_v.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 41fc5e99ec..ae8883e8e8 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -665,7 +665,7 @@ bool VideoDriver_SDL_Base::ToggleFullscreen(bool fullscreen) if (fullscreen) { /* Find fullscreen window size */ SDL_DisplayMode dm; - if (SDL_GetCurrentDisplayMode(0, &dm) < 0) { + if (SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(this->sdl_window), &dm) < 0) { Debug(driver, 0, "SDL_GetCurrentDisplayMode() failed: {}", SDL_GetError()); } else { SDL_SetWindowSize(this->sdl_window, dm.w, dm.h); From 53fa54f8e9babc3a28226a1f7e7ec6478431e558 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 15 Jan 2024 00:21:11 +0000 Subject: [PATCH 14/14] Fix e1f5be62: Clear font cache when toggling sprite font. (#11780) This is necessary for the sprite font height and ascender to be updated correctly. --- src/settings_gui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index f4ec1ba298..3fededad82 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -573,6 +573,7 @@ struct GameOptionsWindow : Window { InitFontCache(false); InitFontCache(true); + ClearFontCache(); SetupWidgetDimensions(); ReInitAllWindows(true); break;