From aeba1d792f053fe2af0ec88affe6484e51e9debb Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Mon, 7 Jan 2019 19:44:32 -0500 Subject: [PATCH 1/2] Retina Bitmaps If scalable bitmaps are present we can begin to implement zoom. Step one is to implement Mac Retina display. We do that here by loading 2x bitmaps if available and drawing them at 0.5x scale. On retina displays this looks great. On regular displays it is a no-op basically. See #226 for more. None of this is activated if the skins aren't installed and by default it falls back to the standard bitmaps. --- scripts/macOS/package-au.sh | 4 +- scripts/macOS/package-vst.sh | 5 ++- scripts/macOS/package-vst3.sh | 4 +- src/common/gui/CScalableBitmap.cpp | 63 ++++++++++++++++++++++++++++++ src/common/gui/CScalableBitmap.h | 21 ++++++++++ src/common/gui/SurgeBitmaps.cpp | 14 ++++++- 6 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/common/gui/CScalableBitmap.cpp create mode 100644 src/common/gui/CScalableBitmap.h diff --git a/scripts/macOS/package-au.sh b/scripts/macOS/package-au.sh index d2986e6dfe4..e03d9c3ed9c 100755 --- a/scripts/macOS/package-au.sh +++ b/scripts/macOS/package-au.sh @@ -37,7 +37,9 @@ cp -R "$BUNDLE_RES_SRC_LOCATION" "$BUNDLE_DIR/Contents/Resources" if [[ -z "$SURGE_USE_VECTOR_SKIN" ]]; then cp $BITMAP_SRC_LOCATION/* "$BUNDLE_DIR/Contents/Resources/" else - rm "$BUNDLE_DIR/Contents/Resources/bmp?????.png" + rm "$BUNDLE_DIR/Contents/Resources/bmp*.png" cp $VECTOR_BITMAP_SRC_LOCATION/bmp?????.png "$BUNDLE_DIR/Contents/Resources/" + mkdir "$BUNDLE_DIR/Contents/Resources/scalable" + cp $VECTOR_BITMAP_SRC_LOCATION/*png "$BUNDLE_DIR/Contents/Resources/scalable" fi diff --git a/scripts/macOS/package-vst.sh b/scripts/macOS/package-vst.sh index aca4b39601a..133b1b840fc 100755 --- a/scripts/macOS/package-vst.sh +++ b/scripts/macOS/package-vst.sh @@ -37,7 +37,10 @@ cp -R "$BUNDLE_RES_SRC_LOCATION" "$BUNDLE_DIR/Contents/Resources" if [[ -z "$SURGE_USE_VECTOR_SKIN" ]]; then cp $BITMAP_SRC_LOCATION/* "$BUNDLE_DIR/Contents/Resources/" else - rm "$BUNDLE_DIR/Contents/Resources/bmp?????.png" + rm "$BUNDLE_DIR/Contents/Resources/bmp*.png" cp $VECTOR_BITMAP_SRC_LOCATION/bmp?????.png "$BUNDLE_DIR/Contents/Resources/" + mkdir "$BUNDLE_DIR/Contents/Resources/scalable" + cp $VECTOR_BITMAP_SRC_LOCATION/*png "$BUNDLE_DIR/Contents/Resources/scalable" fi + diff --git a/scripts/macOS/package-vst3.sh b/scripts/macOS/package-vst3.sh index 6436359c03f..87bb61679c2 100755 --- a/scripts/macOS/package-vst3.sh +++ b/scripts/macOS/package-vst3.sh @@ -37,7 +37,9 @@ cp -R "$BUNDLE_RES_SRC_LOCATION" "$BUNDLE_DIR/Contents/Resources" if [[ -z "$SURGE_USE_VECTOR_SKIN" ]]; then cp $BITMAP_SRC_LOCATION/* "$BUNDLE_DIR/Contents/Resources/" else - rm "$BUNDLE_DIR/Contents/Resources/bmp?????.png" + rm "$BUNDLE_DIR/Contents/Resources/bmp*.png" cp $VECTOR_BITMAP_SRC_LOCATION/bmp?????.png "$BUNDLE_DIR/Contents/Resources/" + mkdir "$BUNDLE_DIR/Contents/Resources/scalable" + cp $VECTOR_BITMAP_SRC_LOCATION/*png "$BUNDLE_DIR/Contents/Resources/scalable" fi diff --git a/src/common/gui/CScalableBitmap.cpp b/src/common/gui/CScalableBitmap.cpp new file mode 100644 index 00000000000..be5b3789888 --- /dev/null +++ b/src/common/gui/CScalableBitmap.cpp @@ -0,0 +1,63 @@ +#include "CScalableBitmap.h" +#if MAC +#include +#endif + +CScalableBitmap::CScalableBitmap( CResourceDescription desc ) : CBitmap( desc ) +{ + int id = 0; + if( desc.type == CResourceDescription::kIntegerType ) + id = (int32_t)desc.u.id; + + scales = {{ 100, 200 }}; + scaleFilePostfixes[ 100 ] = ""; + scaleFilePostfixes[ 200 ] = "@2x"; + + //fprintf( stderr, "\n" ); + for( auto sc : scales ) + { + auto postfix = scaleFilePostfixes[ sc ]; + char filename [PATH_MAX]; + sprintf (filename, "scalable/bmp%05d%s.png", id, postfix.c_str() ); + + CBitmap *tmp = new CBitmap( CResourceDescription( filename ) ); + //fprintf( stderr, "%s, Scale=%d, Dim=(%lf x %lf)\n", filename, sc, tmp->getWidth(), tmp->getHeight() ); + + if( tmp->getWidth() > 0 ) + { + scaledBitmaps[ sc ] = tmp; + } + else + { + scaledBitmaps[ sc ] = NULL; + } + + } +} + +void CScalableBitmap::draw (CDrawContext* context, const CRect& rect, const CPoint& offset, float alpha ) +{ + /* + ** For now this is a fixed 'retina' style draw of using 2x bitmaps at 0.5 scale if they exist + */ + if( scaledBitmaps[ 200 ] != NULL ) + { + CGraphicsTransform tf = CGraphicsTransform().scale( 0.5, 0.5 ); + CGraphicsTransform invtf = tf.inverse(); + + CDrawContext::Transform tr( *context, tf ); + + // Have to de-const these to do the transform alas + CRect ncrect = rect; + CRect nr = invtf.transform( ncrect ); + + CPoint ncoff = offset; + CPoint no = invtf.transform( ncoff ); + + scaledBitmaps[ 200 ]->draw( context, nr, no, alpha ); + } + else + { + CBitmap::draw( context, rect, offset, alpha ); + } +} diff --git a/src/common/gui/CScalableBitmap.h b/src/common/gui/CScalableBitmap.h new file mode 100644 index 00000000000..1ece12ac739 --- /dev/null +++ b/src/common/gui/CScalableBitmap.h @@ -0,0 +1,21 @@ +/* +** CScalableBitmap is an implmentation of VSGTUI::CBitmap which can +** load bitmaps at multiple resolutions and draw them scaled accordingly +*/ + +#include + +#include +#include + +class CScalableBitmap : public VSTGUI::CBitmap +{ +public: + CScalableBitmap( CResourceDescription d ); + + std::vector< int > scales; // 100, 150, 200, 300 etc... - int percentages + std::map< int, VSTGUI::CBitmap * > scaledBitmaps; + std::map< int, std::string > scaleFilePostfixes; + + virtual void draw (CDrawContext* context, const CRect& rect, const CPoint& offset, float alpha); +}; diff --git a/src/common/gui/SurgeBitmaps.cpp b/src/common/gui/SurgeBitmaps.cpp index 6b513e16a52..624f7214dbd 100644 --- a/src/common/gui/SurgeBitmaps.cpp +++ b/src/common/gui/SurgeBitmaps.cpp @@ -1,6 +1,14 @@ #include "SurgeBitmaps.h" #include +#if MAC && TARGET_AUDIOUNIT // for now +#define USE_SCALABLE_BITMAPS 1 +#endif + +#ifdef USE_SCALABLE_BITMAPS +#include "CScalableBitmap.h" +#endif + std::map bitmap_registry; static std::atomic_int refCount(0); @@ -13,7 +21,7 @@ SurgeBitmaps::SurgeBitmaps() addEntry(IDB_BUTTON_ABOUT); addEntry(IDB_ABOUT); addEntry(IDB_FILTERBUTTONS); - addEntry(IDB_OSCSWITCH); + addEntry(IDB_OSCSWITCH); addEntry(IDB_FILTERSUBTYPE); addEntry(IDB_RELATIVE_TOGGLE); addEntry(IDB_OSCSELECT); @@ -72,7 +80,11 @@ void SurgeBitmaps::addEntry(int id) { assert(bitmap_registry.find(id) == bitmap_registry.end()); +#ifdef USE_SCALABLE_BITMAPS + VSTGUI::CBitmap *bitmap = new CScalableBitmap(CResourceDescription(id)); +#else VSTGUI::CBitmap* bitmap = new VSTGUI::CBitmap(CResourceDescription(id)); +#endif bitmap_registry[id] = bitmap; } From 5c77a49550955f9eac9aac4adc53425cfe91dbf6 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Sat, 12 Jan 2019 13:13:09 -0500 Subject: [PATCH 2/2] Respond to @jsakkine review comments with diffs. Activate for VST2 and VST3 also, which was in the scripts, but not the code. --- src/common/gui/CScalableBitmap.cpp | 43 +++++++++++++++++------------- src/common/gui/SurgeBitmaps.cpp | 2 +- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/common/gui/CScalableBitmap.cpp b/src/common/gui/CScalableBitmap.cpp index be5b3789888..37f013ea96c 100644 --- a/src/common/gui/CScalableBitmap.cpp +++ b/src/common/gui/CScalableBitmap.cpp @@ -3,33 +3,40 @@ #include #endif -CScalableBitmap::CScalableBitmap( CResourceDescription desc ) : CBitmap( desc ) +CScalableBitmap::CScalableBitmap(CResourceDescription desc) : CBitmap(desc) { int id = 0; - if( desc.type == CResourceDescription::kIntegerType ) + if(desc.type == CResourceDescription::kIntegerType) id = (int32_t)desc.u.id; - + + /* + ** At this stage this scales array may seem like overkill since it only has two + ** values. But to impelemnt scalability we will end up with multiple sizes, including + ** 1.5x maybe 1.25x and so on. So build the architecture now to support that even + ** though we only populate with two types. And since our sizes will include a 1.25x + ** hash on integer percentages (so 100 -> 1x), not on floats. + */ + scales = {{ 100, 200 }}; scaleFilePostfixes[ 100 ] = ""; scaleFilePostfixes[ 200 ] = "@2x"; - //fprintf( stderr, "\n" ); - for( auto sc : scales ) + for(auto sc : scales) { - auto postfix = scaleFilePostfixes[ sc ]; + auto postfix = scaleFilePostfixes[sc]; + char filename [PATH_MAX]; - sprintf (filename, "scalable/bmp%05d%s.png", id, postfix.c_str() ); + sprintf (filename, "scalable/bmp%05d%s.png", id, postfix.c_str()); - CBitmap *tmp = new CBitmap( CResourceDescription( filename ) ); - //fprintf( stderr, "%s, Scale=%d, Dim=(%lf x %lf)\n", filename, sc, tmp->getWidth(), tmp->getHeight() ); + CBitmap *tmp = new CBitmap(CResourceDescription( filename )); - if( tmp->getWidth() > 0 ) + if(tmp->getWidth() > 0) { - scaledBitmaps[ sc ] = tmp; + scaledBitmaps[sc] = tmp; } else { - scaledBitmaps[ sc ] = NULL; + scaledBitmaps[sc] = NULL; } } @@ -40,24 +47,24 @@ void CScalableBitmap::draw (CDrawContext* context, const CRect& rect, const CPoi /* ** For now this is a fixed 'retina' style draw of using 2x bitmaps at 0.5 scale if they exist */ - if( scaledBitmaps[ 200 ] != NULL ) + if (scaledBitmaps[ 200 ] != NULL) { CGraphicsTransform tf = CGraphicsTransform().scale( 0.5, 0.5 ); CGraphicsTransform invtf = tf.inverse(); - CDrawContext::Transform tr( *context, tf ); + CDrawContext::Transform tr(*context, tf); // Have to de-const these to do the transform alas CRect ncrect = rect; - CRect nr = invtf.transform( ncrect ); + CRect nr = invtf.transform(ncrect); CPoint ncoff = offset; - CPoint no = invtf.transform( ncoff ); + CPoint no = invtf.transform(ncoff); - scaledBitmaps[ 200 ]->draw( context, nr, no, alpha ); + scaledBitmaps[ 200 ]->draw(context, nr, no, alpha); } else { - CBitmap::draw( context, rect, offset, alpha ); + CBitmap::draw(context, rect, offset, alpha); } } diff --git a/src/common/gui/SurgeBitmaps.cpp b/src/common/gui/SurgeBitmaps.cpp index 624f7214dbd..b896aaf6603 100644 --- a/src/common/gui/SurgeBitmaps.cpp +++ b/src/common/gui/SurgeBitmaps.cpp @@ -1,7 +1,7 @@ #include "SurgeBitmaps.h" #include -#if MAC && TARGET_AUDIOUNIT // for now +#if MAC #define USE_SCALABLE_BITMAPS 1 #endif