Skip to content

Commit

Permalink
Merge pull request #355 from baconpaul/redo-zoom-au-348
Browse files Browse the repository at this point in the history
Smart bitmap selection on Zoom. Closes #348
  • Loading branch information
baconpaul authored Jan 20, 2019
2 parents 4279f04 + 485a124 commit 2377896
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 65 deletions.
1 change: 0 additions & 1 deletion src/common/gui/.#SurgeGUIEditor.cpp

This file was deleted.

56 changes: 42 additions & 14 deletions src/common/gui/CScalableBitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,31 @@
#include <CoreFoundation/CoreFoundation.h>
#endif

// Remember this is user zoom * display zoom. See comment in CScalableBitmap.h
int CScalableBitmap::currentPhysicalZoomFactor = 100;
void CScalableBitmap::setPhysicalZoomFactor(int zoomFactor)
{
currentPhysicalZoomFactor = zoomFactor;
}

CScalableBitmap::CScalableBitmap(CResourceDescription desc) : CBitmap(desc)
{
int id = 0;
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.
** Remember, Scales are the percentage scale in units of percents. So 100 is 1x.
** This integerification allows us to hash on the scale values and still support
** things like a 1.25 bitmap set.
*/

scales = {{ 100, 200 }};
scales = {{ 100, 150, 200, 300, 400 }}; // This is the collection of sizes we currently ask skins to export.
scaleFilePostfixes[ 100 ] = "";
scaleFilePostfixes[ 150 ] = "@15x";
scaleFilePostfixes[ 200 ] = "@2x";
scaleFilePostfixes[ 300 ] = "@3x";
scaleFilePostfixes[ 400 ] = "@4x";

for(auto sc : scales)
{
Expand All @@ -40,17 +48,35 @@ CScalableBitmap::CScalableBitmap(CResourceDescription desc) : CBitmap(desc)
}

}
lastSeenZoom = currentPhysicalZoomFactor;
}


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)
if (lastSeenZoom != currentPhysicalZoomFactor)
{
CGraphicsTransform tf = CGraphicsTransform().scale( 0.5, 0.5 );
CGraphicsTransform invtf = tf.inverse();
int ns = -1;
for (auto s : scales)
{
if (s >= currentPhysicalZoomFactor && ns < 0)
ns = s;
}
if (ns<0)
{
ns = scales.back();
}
bestFitScaleGroup = ns;
lastSeenZoom = currentPhysicalZoomFactor;
}

// Check if my bitmaps are there and if so use them
if (scaledBitmaps[ bestFitScaleGroup ] != NULL)
{
// Seems like you would do this backwards; but the TF shrinks and the invtf regrows for positioning
// but it is easier to calculate the grow one since it is at our scale
CGraphicsTransform invtf = CGraphicsTransform().scale( bestFitScaleGroup / 100.0, bestFitScaleGroup / 100.0 );
CGraphicsTransform tf = invtf.inverse();

CDrawContext::Transform tr(*context, tf);

Expand All @@ -61,10 +87,12 @@ void CScalableBitmap::draw (CDrawContext* context, const CRect& rect, const CPoi
CPoint ncoff = offset;
CPoint no = invtf.transform(ncoff);

scaledBitmaps[ 200 ]->draw(context, nr, no, alpha);
scaledBitmaps[ bestFitScaleGroup ]->draw(context, nr, no, alpha);
}
else
{
// and if not, fall back to the default bitmap
CBitmap::draw(context, rect, offset, alpha);
}
}

19 changes: 18 additions & 1 deletion src/common/gui/CScalableBitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,26 @@ class CScalableBitmap : public VSTGUI::CBitmap
public:
CScalableBitmap( CResourceDescription d );

virtual void draw (CDrawContext* context, const CRect& rect, const CPoint& offset, float alpha);

/*
** The 'zoom factor' is set statically across all bitmaps since it is a
** function of the current editor which contains them.
**
** If in the future we have a non 1:1 editor -> instance relationship we
** may need to reconsider the management of this factor.
**
** This zoom factor is the product of the logical (user) zoom factor
** and any zoom the display may apply, which is checked in SurgeGUIEditor::getDisplayBackingScale
** and applied *before* this call. See SurgeGUIEditor::setZoomFactor.
*/
static void setPhysicalZoomFactor (int zoomFactor); // See comment on zoom factor units in SurgeGUIEditor.h

private:
std::vector< int > scales; // 100, 150, 200, 300 etc... - int percentages
std::map< int, VSTGUI::CBitmap * > scaledBitmaps;
std::map< int, std::string > scaleFilePostfixes;
int lastSeenZoom, bestFitScaleGroup;

virtual void draw (CDrawContext* context, const CRect& rect, const CPoint& offset, float alpha);
static int currentPhysicalZoomFactor;
};
107 changes: 63 additions & 44 deletions src/common/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "CAboutBox.h"
#include "vstcontrols.h"
#include "SurgeBitmaps.h"
#include "CScalableBitmap.h"
#include "CNumberField.h"
#include "UserInteractions.h"

Expand Down Expand Up @@ -64,7 +65,6 @@ enum special_tags
tag_store_comments,
tag_mod_source0,
tag_mod_source_end = tag_mod_source0 + n_modsources,
tag_mp_zoom,
tag_settingsmenu,
// tag_metaparam,
// tag_metaparam_end = tag_metaparam+n_customcontrollers,
Expand Down Expand Up @@ -130,7 +130,7 @@ SurgeGUIEditor::SurgeGUIEditor(void* effect, SurgeSynthesizer* synth) : super(ef
_idleTimer = new CVSTGUITimer([this](CVSTGUITimer* timer) { idle(); }, 50, false);
#endif
zoom_callback = [](SurgeGUIEditor* f) {};
zoomFactor = 100;
setZoomFactor(100);
}

SurgeGUIEditor::~SurgeGUIEditor()
Expand Down Expand Up @@ -1127,22 +1127,6 @@ void SurgeGUIEditor::openOrRecreateEditor()
getSurgeBitmap(IDB_BUTTON_MENU), nopoint, false);
frame->addView(b_settingsMenu);

#if TARGET_AUDIOUNIT
// ZOOM CONTROL for now is only implemented in the Audio Unit host
CHSwitch2* mp_zoom =
new CHSwitch2(CRect(892 - 77, 526, 892 - 40, 526 + 12), this, tag_mp_zoom, 2, 12, 1, 2,
getSurgeBitmap(IDB_BUTTON_MINUSPLUS), nopoint, false);
frame->addView(mp_zoom);
CTextLabel* Comments = new CTextLabel(CRect(892 - 137, 526, 892 - 77, 526 + 12), "Zoom");

Comments->setTransparency(true);
Comments->setFont(minifont);
Comments->setFontColor(kBlackCColor);
Comments->setHoriAlign(kRightText);
frame->addView(Comments);
// END ZOOM CONTROL
#endif

infowindow = new CParameterTooltip(CRect(0, 0, 0, 0));
frame->addView(infowindow);

Expand Down Expand Up @@ -2038,15 +2022,6 @@ void SurgeGUIEditor::valueChanged(CControl* control)
return;
}
break;
case tag_mp_zoom:
{
if (control->getValue() > 0.5f)
zoomInDir(1);
else
zoomInDir(-1);
return;
}
break;
case tag_settingsmenu:
{
CRect r = control->getViewSize();
Expand Down Expand Up @@ -2423,56 +2398,100 @@ bool SurgeGUIEditor::showPatchStoreDialog(patchdata* p,
return false;
}

void SurgeGUIEditor::zoomInDir(int dir)
long SurgeGUIEditor::applyParameterOffset(long id)
{
if (dir > 0)
{
zoomFactor += 10;
}
else
{
zoomFactor -= 10;
}
if (zoomFactor < 50)
zoomFactor = 50;
if (zoomFactor > 300)
zoomFactor = 300;
return id-start_paramtags;
}

void SurgeGUIEditor::setZoomFactor(int zf)
{
int dbs = getDisplayBackingScale();
zoomFactor = zf;
zoom_callback(this);

int fullPhysicalZoomFactor = (int)(zf * (dbs / 100.0)); // soo 150 and 200 gets you 300 not 30000!
CScalableBitmap::setPhysicalZoomFactor(fullPhysicalZoomFactor);
}

long SurgeGUIEditor::applyParameterOffset(long id)
int SurgeGUIEditor::getDisplayBackingScale()
{
return id-start_paramtags;
return 200; // hardwire to retina for a moment
}

void SurgeGUIEditor::showSettingsMenu(CRect &menuRect)
{
COptionMenu* settingsMenu =
new COptionMenu(menuRect, 0, 0, 0, 0, kNoDrawStyle | kMultipleCheckStyle);
int eid = 0;
bool handled = false;

int id_about = eid;
settingsMenu->addEntry("About", eid++);

int id_openmanual = eid;
settingsMenu->addEntry("Surge Manual", eid++);

#if SUPPORTS_ZOOM
// Zoom submenus
COptionMenu *zoomSubMenu = new COptionMenu(menuRect, 0, 0, 0, 0, kNoDrawStyle);

int zid = 0;
for(auto s : { 100, 125, 150, 200, 300 }) // These are somewhat arbitrary reasonable defaults
{
std::ostringstream lab;
lab << "Zoom to " << s << "%";
CCommandMenuItem *zcmd = new CCommandMenuItem(lab.str());
zcmd->setActions([this,s,&handled](CCommandMenuItem *m) {
setZoomFactor(s);
handled = true;
}
);
zoomSubMenu->addEntry(zcmd); zid++;
}

zoomSubMenu->addEntry( "-", zid++ );

for(auto jog : { -25, -10, 10, 25 } ) // These are somewhat arbitrary reasonable defaults also
{
std::ostringstream lab;
if( jog > 0 )
lab << "Grow by " << jog << "%";
else
lab << "Shrink by " << -jog << "%";

CCommandMenuItem *zcmd = new CCommandMenuItem(lab.str());
zcmd->setActions([this,jog,&handled](CCommandMenuItem *m) {
setZoomFactor(getZoomFactor() + jog);
handled = true;
}
);
zoomSubMenu->addEntry(zcmd); zid++;
}

settingsMenu->addEntry(zoomSubMenu, "Zoom");
#endif // Supports Zoom

frame->addView(settingsMenu); // add to frame
settingsMenu->setDirty();
settingsMenu->popup();

int command = settingsMenu->getLastResult();
frame->removeView(settingsMenu, true);

if(command == id_about)
if( handled )
{
// Someone else got it
}
else if(command == id_about)
{
if (aboutbox)
((CAboutBox*)aboutbox)->boxShow();
}
else if(command == id_openmanual)
{
Surge::UserInteractions::openURL("https://surge-synthesizer.github.io/surge-manual/Surge.html");
Surge::UserInteractions::openURL("https://surge-synthesizer.github.io/surge-manual/");
}

}

//------------------------------------------------------------------------------------------------
35 changes: 30 additions & 5 deletions src/common/gui/SurgeGUIEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,35 @@ class SurgeGUIEditor : public EditorType, public IControlListener, public IKeybo


void showSettingsMenu(CRect &menuRect);

/*
** Zoom Implementation
**
** Zoom works by the system maintaining a zoom factor (created by user actions)
**
** All zoom factors are set in units of percentages as ints. So no zoom is "100",
** and double size is "200"
*/

void zoomInDir( int dir );
int zoomFactor;
public:
void setZoomCallback( std::function< void(SurgeGUIEditor *) > f ) { zoom_callback = f; }
int getZoomFactor() { return zoomFactor; }
void setZoomFactor( int zf ) { zoomFactor = zf; zoom_callback( this ); }
private:
void setZoomCallback(std::function< void(SurgeGUIEditor *) > f) {
zoom_callback = f;
setZoomFactor(getZoomFactor()); // notify the new callback
}
int getZoomFactor() { return zoomFactor; }
void setZoomFactor(int zf);

/*
** Display backing scale is very OS dependent, so is implemented in src/(mac|win|linux)/(Mac|Win|Linux)SurgeGuiEditor.(cpp|mm) and so on
** 'BackignScale' is the term for the difference between a logical and physical pixel. So on a mac retina display it woudl be '2.0'
** then scaled up to an integer to be '200'.
**
** As of the current state, this is just a function which returns '200' and the above implementation is not yet in place.
*/
int getDisplayBackingScale();

private:
std::function< void(SurgeGUIEditor *) > zoom_callback;

SurgeBitmaps bitmap_keeper;
Expand Down Expand Up @@ -131,3 +152,7 @@ class SurgeGUIEditor : public EditorType, public IControlListener, public IKeybo
void* _effect = nullptr;
CVSTGUITimer* _idleTimer = nullptr;
};

#if TARGET_AUDIOUNIT && MAC
#define SUPPORTS_ZOOM 1
#endif

0 comments on commit 2377896

Please sign in to comment.