From 27dc87578a3d5ba75ae3d09a4b104422d4957c8f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 8 Jul 2021 05:45:42 +0200 Subject: [PATCH] GaugeVario: render background without bitmap The background bitmap looks ugly and there isn't one for the "kt" unit. By drawing at runtime, we have more flexibility, and we can easily adapt to other units. This is a naive unoptimized version which does not try to pre-calculate line positions. Closes https://github.com/XCSoar/XCSoar/issues/305 --- Data/XCSoar.rc | 2 - Data/bitmaps/vario_scale_b.bmp | Bin 7318 -> 0 bytes Data/bitmaps/vario_scale_c.bmp | Bin 14998 -> 0 bytes Data/icons/instrument_vario1.svg | 165 ---------------------------- Data/icons/instrument_vario2.svg | 180 ------------------------------- Data/icons/vario1.svg | 155 -------------------------- NEWS.txt | 2 + build/android.mk | 8 -- src/Gauge/GaugeVario.cpp | 94 ++++++++++++++-- src/Look/VarioLook.cpp | 8 +- src/Look/VarioLook.hpp | 6 +- src/Resources.hpp | 2 - 12 files changed, 94 insertions(+), 528 deletions(-) delete mode 100644 Data/bitmaps/vario_scale_b.bmp delete mode 100644 Data/bitmaps/vario_scale_c.bmp delete mode 100644 Data/icons/instrument_vario1.svg delete mode 100644 Data/icons/instrument_vario2.svg delete mode 100644 Data/icons/vario1.svg diff --git a/Data/XCSoar.rc b/Data/XCSoar.rc index 903f8061364..ab341f4eb8b 100644 --- a/Data/XCSoar.rc +++ b/Data/XCSoar.rc @@ -192,8 +192,6 @@ BITMAP_ICON(IDB_POWER_PLANT, "map_power_plant") BITMAP_ICON(IDB_POWER_PLANT_HD, "map_power_plant_160") BITMAP_ICON(IDB_THERMAL_HOTSPOT, "map_thermal_hotspot") BITMAP_ICON(IDB_THERMAL_HOTSPOT_HD, "map_thermal_hotspot_160") -BITMAP_BITMAP(IDB_VARIOSCALEA, "vario_scale_b") -BITMAP_BITMAP(IDB_VARIOSCALEC, "vario_scale_c") #ifdef XCSOAR_TESTING BITMAP_GRAPHIC(IDB_TITLE, "title_red_110") BITMAP_GRAPHIC(IDB_TITLE_HD, "title_red_320") diff --git a/Data/bitmaps/vario_scale_b.bmp b/Data/bitmaps/vario_scale_b.bmp deleted file mode 100644 index 2f7326556ab0d601dfc3eb35904cb54e05b4540d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7318 zcmbuEYiv|S6oAim7eZUjVx&f;Ph*#ci9s$9GO-HEhN5 ziNp8X=^FOu52~v7iF6Iy@>hpS)vyC4+or5!r6q;XQ)4kHYs#G2dVO4G=%`szsQVMq zKX$rQlVN7--L_Fok!;kK9^NfeL@1f0-DOy(_(_%WiQ6ORXAqqslJU_f>dpiw{*S*0+moZ1$y8WT>$lAKa5 z+3(0oa?}qrIkGJ&t?)^WS*Oe?Z`TT1u?_u7bP3AVtSeAuG zYxia&i)sTM+9F%yIh2S|Y-WDkGUWReO!%|`wZ>$6fe*5y0xJ57WY6mc2J!-GT}iS7 z!-U--6Ka+DPHhiacEhF~vc4&4eGggeypKq`vn%vP7WFMNR#%kyn4!9Y?KTWZEDg8# zlA*es4Sj1YGH0{57>dlw zW)zY~*LIkinX$-JnqVOXVUt-Fg+-cAn94254qa1YYK)mC8y`U~GSau-hIaoD|01GIuZF)`)l*>ol6h zGJi^-Sl?w7Yxn|MIWo40Vn<24S(5#RWZ4qJZb-jburp+tdV($Zm9(2KBiQgUlFgW> z0)qnc!j74;^is23^-q#A&vysG2MWHVAeOl;$jB5ZpzBMvRX**Uqkpqh{{lU(vedYO zAIY|&=YsDf=FN%GbKx_uwl~Ju8rdVkFz34QXpoU90Qsy}O_knadSW@&Nn)qM_Z#H; zeAzmWC2s`33-8J51ww$r0k66zhTo%>03#Ff`3^>*<~NTeZzRc1n7_YK`n#Vbzxx%t zFMYoOK<#s|lLiyAZTw+0kNp)k%_Z;akj-a533=>ep(n@w+0f#Lef(GRa5ik-6>=g)ol_vk`KZ~j)!}v_pL1D`^We-4n#y95u$#|0G@tWtOJBdR zAN&!8rOw^tc^~_?&UoGzz7eyZLHI_R6S~&2eIxaTLfgI(qkn_9wb`%2aOq&FYxH(4 zuV#BJ*ie|l5x&LQ66ccd;kzGB8U09>H}!Yj7EM|U9n?-@X(_8a^Gg;QHY?F3NS0B4 zGl=By*IkuR`AEUBk%ylUa``9k2pD$kLLPomh-7Ybz0e1?yYsj zxahJ(`JYj|jZsU2bL15y~IRb$@j8K2Zh-QPPumZ}ks(Z}qacx0+IfBfO8|g0`U}=RUXAD_@=Y iec7q)&HDQ?JD1RPjat^u>R;_Wol^pe#Vp*48u@=_(w}_* diff --git a/Data/bitmaps/vario_scale_c.bmp b/Data/bitmaps/vario_scale_c.bmp deleted file mode 100644 index db7d716779d5b564862ccc0df87f32e80096acad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14998 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 - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Data/icons/instrument_vario2.svg b/Data/icons/instrument_vario2.svg deleted file mode 100644 index 6a1f94141c8..00000000000 --- a/Data/icons/instrument_vario2.svg +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - 2 - 2 - 4 - 6 - 4 - 6 - diff --git a/Data/icons/vario1.svg b/Data/icons/vario1.svg deleted file mode 100644 index 13e468c955e..00000000000 --- a/Data/icons/vario1.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - 1 - 2 - 3 - 1 - 2 - 3 - - diff --git a/NEWS.txt b/NEWS.txt index 6a325a1baae..902537586c5 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,4 +1,6 @@ Version 7.11 - not yet released +* user interface + - new vario gauge background Version 7.10 - 2021/07/09 * weather diff --git a/build/android.mk b/build/android.mk index f867115395d..81c32174747 100644 --- a/build/android.mk +++ b/build/android.mk @@ -154,14 +154,6 @@ $(SOUND_FILES): $(RAW_DIR)/%.ogg: Data/sound/%.wav | $(RAW_DIR)/dirstamp PNG1 := $(patsubst Data/bitmaps/%.bmp,$(DRAWABLE_DIR)/%.png,$(BMP_BITMAPS)) -# workaround for an ImageMagick bug (observed with the Debian package -# 8:6.7.7.10-2): it corrupts 4-bit gray-scale images when converting -# BMP to PNG (TRAC #2220) -PNG1b := $(filter $(DRAWABLE_DIR)/vario_scale_%.png,$(PNG1)) -PNG1 := $(filter-out $(DRAWABLE_DIR)/vario_scale_%.png,$(PNG1)) -$(DRAWABLE_DIR)/vario_scale_%.png: Data/bitmaps/vario_scale_%.bmp | $(DRAWABLE_DIR)/dirstamp - $(Q)$(IM_PREFIX)convert -depth 8 $< $@ - $(PNG1): $(DRAWABLE_DIR)/%.png: Data/bitmaps/%.bmp | $(DRAWABLE_DIR)/dirstamp $(Q)$(IM_PREFIX)convert $< $@ diff --git a/src/Gauge/GaugeVario.cpp b/src/Gauge/GaugeVario.cpp index e79894d1ff3..407bf8a6b64 100644 --- a/src/Gauge/GaugeVario.cpp +++ b/src/Gauge/GaugeVario.cpp @@ -28,6 +28,7 @@ Copyright_License { #include "Renderer/UnitSymbolRenderer.hpp" #include "Math/FastRotation.hpp" #include "Units/Units.hpp" +#include "Units/Descriptor.hpp" #include "util/Clamp.hpp" #define DELTA_V_STEP 4. @@ -173,12 +174,93 @@ GaugeVario::GaugeVario(const FullBlackboard &_blackboard, Create(parent, rc, style); } +static constexpr int +WidthToHeight(int width) noexcept +{ + return width * 112 / 100; +} + +static constexpr PixelPoint +TransformRotatedPoint(IntPoint2D pt, IntPoint2D offset) noexcept +{ + return { pt.x + offset.x, WidthToHeight(pt.y) + offset.y + 1 }; +} + inline void GaugeVario::RenderBackground(Canvas &canvas, const PixelRect &rc) noexcept { - canvas.Stretch(rc.GetTopLeft(), rc.GetSize(), - look.background_bitmap, - {(int)look.background_x, 0}, {58, 120}); + canvas.Clear(look.background_color); + + canvas.Select(look.arc_pen); + + std::array arc; + + const int arc_padding = look.arc_label_font.GetHeight(); + + const int x_radius = rc.GetWidth() - arc_padding; + const int y_radius = WidthToHeight(x_radius); + + for (std::size_t i = 0; i < arc.size(); ++i) { + const unsigned angle = INT_ANGLE_RANGE / 2 + + i * INT_ANGLE_RANGE / 2 / (arc.size() - 1); + const PixelPoint delta(ISINETABLE[angle] * x_radius / 1024, + -ISINETABLE[(angle + INT_QUARTER_CIRCLE) % INT_ANGLE_RANGE] * y_radius / 1024); + + arc[i] = geometry.offset + delta; + } + + canvas.DrawPolyline(arc.data(), arc.size()); + + canvas.Select(look.tick_pen); + canvas.Select(look.arc_label_font); + canvas.SetTextColor(look.dimmed_text_color); + canvas.SetBackgroundTransparent(); + + int tick_value_step = 1; + const auto &unit_descriptor = + Units::unit_descriptors[(std::size_t)Units::current.vertical_speed_unit]; + const double unit_factor = unit_descriptor.factor_to_user; + + switch (Units::current.vertical_speed_unit) { + case Unit::FEET_PER_MINUTE: + tick_value_step = 200; + break; + + default: + break; + } + + const Angle tick_angle_step = Angle::QuarterCircle() * tick_value_step + / unit_factor / GAUGEVARIORANGE; + + const int n_ticks = GAUGEVARIORANGE / (tick_value_step / unit_factor); + + const int tick_length = Layout::GetTextPadding() * 4; + + const IntPoint2D tick_start{1 - x_radius, 0}; + const IntPoint2D tick_end{-tick_length - x_radius, 0}; + const IntPoint2D label_center{-x_radius - arc_padding / 2 - tick_length, 0}; + + for (int i = -n_ticks; i < n_ticks; ++i) { + Angle angle = tick_angle_step * i; + const FastIntegerRotation r{angle}; + + canvas.DrawLine(TransformRotatedPoint(r.Rotate(tick_start), + geometry.offset), + TransformRotatedPoint(r.Rotate(tick_end), + geometry.offset)); + + TCHAR label[16]; + StringFormatUnsafe(label, _T("%d"), i * tick_value_step); + + const auto label_size = canvas.CalcTextSize(label); + + const auto label_position = TransformRotatedPoint(r.Rotate(label_center), + geometry.offset) + - label_size / 2U; + + canvas.DrawText(label_position, label); + } } void @@ -279,12 +361,6 @@ GaugeVario::OnPaintBuffer(Canvas &canvas) RenderZero(canvas); } -static constexpr PixelPoint -TransformRotatedPoint(IntPoint2D pt, IntPoint2D offset) noexcept -{ - return { pt.x + offset.x, (pt.y * 112 / 100) + offset.y + 1 }; -} - void GaugeVario::MakePolygon(const int i) noexcept { diff --git a/src/Look/VarioLook.cpp b/src/Look/VarioLook.cpp index 16e31275b28..c6f78d1ce69 100644 --- a/src/Look/VarioLook.cpp +++ b/src/Look/VarioLook.cpp @@ -53,14 +53,14 @@ VarioLook::Initialise(bool _inverse, bool _colors, sink_brush.Create(sink_color); lift_brush.Create(lift_color); + arc_pen.Create(Layout::ScalePenWidth(2), text_color); + tick_pen.Create(Layout::ScalePenWidth(1), text_color); + arc_label_font.Load(FontDescription{Layout::FontScale(14), true}); + thick_background_pen.Create(Layout::Scale(5), background_color); thick_sink_pen.Create(Layout::Scale(5), sink_color); thick_lift_pen.Create(Layout::Scale(5), lift_color); - background_bitmap.Load(Units::GetUserVerticalSpeedUnit() == Unit::KNOTS - ? IDB_VARIOSCALEC : IDB_VARIOSCALEA); - background_x = inverse ? 58 : 0; - climb_bitmap.Load(inverse ? IDB_CLIMBSMALLINV : IDB_CLIMBSMALL); text_font = &_text_font; diff --git a/src/Look/VarioLook.hpp b/src/Look/VarioLook.hpp index 8853f6c04ca..447c06d4a37 100644 --- a/src/Look/VarioLook.hpp +++ b/src/Look/VarioLook.hpp @@ -39,13 +39,13 @@ struct VarioLook { Color sink_color, lift_color; + Pen arc_pen, tick_pen; + Font arc_label_font; + Brush sink_brush, lift_brush; Pen thick_background_pen, thick_sink_pen, thick_lift_pen; - Bitmap background_bitmap; - unsigned background_x; - Bitmap climb_bitmap; const Font *text_font; diff --git a/src/Resources.hpp b/src/Resources.hpp index 31121152ca7..d00ecd770ca 100644 --- a/src/Resources.hpp +++ b/src/Resources.hpp @@ -54,10 +54,8 @@ MAKE_RESOURCE(IDB_OUTFIELD_REACHABLE, 291); MAKE_RESOURCE(IDB_OUTFIELD_REACHABLE_HD, 5291); MAKE_RESOURCE(IDB_OUTFIELD_UNREACHABLE, 292); MAKE_RESOURCE(IDB_OUTFIELD_UNREACHABLE_HD, 5292); -MAKE_RESOURCE(IDB_VARIOSCALEA, 293); MAKE_RESOURCE(IDB_CLIMBSMALL, 313); MAKE_RESOURCE(IDB_CLIMBSMALLINV, 314); -MAKE_RESOURCE(IDB_VARIOSCALEC, 315); MAKE_RESOURCE(IDB_THERMALSOURCE, 316); MAKE_RESOURCE(IDB_THERMALSOURCE_HD, 5316); MAKE_RESOURCE(IDB_TARGET, 320);