From c7802e7ff867e46e4c924e7131e3e0d3d39e3c0e Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 1 Oct 2020 11:48:50 +0100 Subject: [PATCH] Adjust ruler text on non-HDPI displays. Fixes https://gitlab.com/kicad/code/kicad/issues/5654 --- common/preview_items/arc_assistant.cpp | 3 - common/preview_items/preview_utils.cpp | 151 ++++++++++--------- common/preview_items/ruler_item.cpp | 93 +++--------- common/preview_items/two_point_assistant.cpp | 3 - common/richio.cpp | 1 + include/preview_items/preview_utils.h | 18 ++- 6 files changed, 123 insertions(+), 146 deletions(-) diff --git a/common/preview_items/arc_assistant.cpp b/common/preview_items/arc_assistant.cpp index 6e3a95fe24..81ea0b4f53 100644 --- a/common/preview_items/arc_assistant.cpp +++ b/common/preview_items/arc_assistant.cpp @@ -91,9 +91,6 @@ void ARC_ASSISTANT::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const gal.ResetTextAttributes(); - // constant text size on screen - SetConstantGlyphHeight( gal, 12.0 ); - // angle reference arc size const double innerRad = 12.0 / gal.GetWorldScale(); diff --git a/common/preview_items/preview_utils.cpp b/common/preview_items/preview_utils.cpp index ac43993865..5a6d811d16 100644 --- a/common/preview_items/preview_utils.cpp +++ b/common/preview_items/preview_utils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include double KIGFX::PREVIEW::PreviewOverlayDeemphAlpha( bool aDeemph ) { @@ -29,66 +30,86 @@ double KIGFX::PREVIEW::PreviewOverlayDeemphAlpha( bool aDeemph ) } -static wxString formatPreviewDimension( double aVal, EDA_UNITS aUnits ) -{ - int precision = 4; - - // show a sane precision for the preview, which doesn't need to - // be accurate down to the nanometre - switch( aUnits ) - { - case EDA_UNITS::MILLIMETRES: - precision = 3; // 1um - break; - - case EDA_UNITS::INCHES: - precision = 4; // 0.1mil - break; - - case EDA_UNITS::DEGREES: - precision = 1; // 0.1deg - break; - - case EDA_UNITS::PERCENT: - precision = 1; // 0.1% - break; - - case EDA_UNITS::UNSCALED: - break; - } - - const wxString fmtStr = wxString::Format( "%%.%df", precision ); - - wxString str = wxString::Format( fmtStr, To_User_Unit( aUnits, aVal ) ); - - const wxString symbol = GetAbbreviatedUnitsLabel( aUnits, false ); - - if( symbol.size() ) - str << " " << symbol; - - return str; -} - - -wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal, EDA_UNITS aUnits ) +wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal, EDA_UNITS aUnits, + bool aIncludeUnits ) { wxString str; if( prefix.size() ) str << prefix << ": "; - str << formatPreviewDimension( aVal, aUnits ); + wxString fmtStr; + + // show a sane precision for the preview, which doesn't need to be accurate down to the + // nanometre + switch( aUnits ) + { + case EDA_UNITS::MILLIMETRES: fmtStr = wxT( "%.3f" ); break; // 1um + case EDA_UNITS::INCHES: fmtStr = wxT( "%.4f" ); break; // 0.1mil + case EDA_UNITS::DEGREES: fmtStr = wxT( "%.1f" ); break; // 0.1deg + case EDA_UNITS::PERCENT: fmtStr = wxT( "%.1f" ); break; // 0.1% + case EDA_UNITS::UNSCALED: fmtStr = wxT( "%f" ); break; + } + + str << wxString::Format( fmtStr, To_User_Unit( aUnits, aVal ) ); + + if( aIncludeUnits ) + str << " " << GetAbbreviatedUnitsLabel( aUnits, false ); + return str; } -void KIGFX::PREVIEW::SetConstantGlyphHeight( KIGFX::GAL& aGal, double aHeight ) +KIGFX::PREVIEW::TEXT_DIMS KIGFX::PREVIEW::SetConstantGlyphHeight( KIGFX::GAL* aGal, + int aRelativeSize ) { - aHeight /= aGal.GetWorldScale(); + constexpr double hdpiSizes[] = { 8, 9, 11, 13, 15 }; + constexpr double sizes[] = { 10, 12, 14, 16, 18 }; - auto glyphSize = aGal.GetGlyphSize(); - glyphSize = glyphSize * ( aHeight / glyphSize.y ); - aGal.SetGlyphSize( glyphSize ); + double height; + double thicknessFactor; + double shadowFactor; + double linePitchFactor; + + HIDPI_GL_CANVAS* canvas = dynamic_cast( aGal ); + + if( canvas && canvas->GetScaleFactor() > 1 ) + { + height = hdpiSizes[ 2 + aRelativeSize ]; + thicknessFactor = 0.15; + shadowFactor = 0.10; + linePitchFactor = 1.7; + } + else + { + height = sizes[ 2 + aRelativeSize ]; + thicknessFactor = 0.20; + shadowFactor = 0.15; + linePitchFactor = 1.9; + } + + height /= aGal->GetWorldScale(); + + VECTOR2D glyphSize = aGal->GetGlyphSize(); + glyphSize = glyphSize * ( height / glyphSize.y ); + aGal->SetGlyphSize( glyphSize ); + + TEXT_DIMS textDims; + + textDims.StrokeWidth = glyphSize.x * thicknessFactor; + textDims.ShadowWidth = glyphSize.x * shadowFactor; + textDims.LinePitch = glyphSize.y * linePitchFactor; + + return textDims; +} + + +KIGFX::COLOR4D KIGFX::PREVIEW::GetShadowColor(class KIGFX::COLOR4D aColor) +{ + if( aColor.GetBrightness() > 0.5 ) + return COLOR4D::BLACK; + else + return COLOR4D::WHITE; } @@ -97,21 +118,20 @@ void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& a const std::vector& aStrings, bool aDrawingDropShadows ) { - KIGFX::GAL* gal = aView->GetGAL(); - VECTOR2D glyphSize = gal->GetGlyphSize(); + KIGFX::GAL* gal = aView->GetGAL(); RENDER_SETTINGS* rs = aView->GetPainter()->GetSettings(); - double linePitch = glyphSize.y * 1.6; - double textThickness = glyphSize.x / 8; - // radius string goes on the right of the cursor centre line - // with a small horizontal offset (enough to keep clear of a - // system cursor if present) - VECTOR2D textPos = aCursorPos; + // constant text size on screen + TEXT_DIMS textDims = SetConstantGlyphHeight( gal ); + + // radius string goes on the right of the cursor centre line with a small horizontal + // offset (enough to keep clear of a system cursor if present) + VECTOR2D textPos = aCursorPos; // if the text goes above the cursor, shift it up if( aTextQuadrant.y > 0 ) { - textPos.y -= linePitch * ( aStrings.size() + 1 ); + textPos.y -= textDims.LinePitch * ( aStrings.size() + 1 ); } if( aTextQuadrant.x < 0 ) @@ -120,7 +140,7 @@ void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& a textPos.x += 15.0 / gal->GetWorldScale(); if( aDrawingDropShadows ) - textPos.x -= textThickness; + textPos.x -= textDims.ShadowWidth; } else { @@ -128,28 +148,23 @@ void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& a textPos.x -= 15.0 / gal->GetWorldScale(); if( aDrawingDropShadows ) - textPos.x += textThickness; + textPos.x += textDims.ShadowWidth; } gal->SetIsFill( false ); gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) ); + gal->SetLineWidth( textDims.StrokeWidth ); if( aDrawingDropShadows ) { - if( gal->GetStrokeColor().GetBrightness() > 0.5 ) - gal->SetStrokeColor( COLOR4D::BLACK.WithAlpha( 0.7 ) ); - else - gal->SetStrokeColor( COLOR4D::WHITE.WithAlpha( 0.7 ) ); - - textThickness *= 3; + gal->SetStrokeColor( GetShadowColor( gal->GetStrokeColor() ) ); + gal->SetLineWidth( gal->GetLineWidth() + 2 * textDims.ShadowWidth ); } - gal->SetLineWidth( textThickness ); - // write strings top-to-bottom for( const wxString& str : aStrings ) { - textPos.y += linePitch; + textPos.y += textDims.LinePitch; gal->StrokeText( str, textPos, 0.0 ); } } diff --git a/common/preview_items/ruler_item.cpp b/common/preview_items/ruler_item.cpp index bc05fd6832..b44e436d0e 100644 --- a/common/preview_items/ruler_item.cpp +++ b/common/preview_items/ruler_item.cpp @@ -29,7 +29,6 @@ #include #include -#include #include using namespace KIGFX::PREVIEW; @@ -38,8 +37,6 @@ static const double maxTickDensity = 10.0; // min pixels between tick mark static const double midTickLengthFactor = 1.5; static const double majorTickLengthFactor = 2.5; -static const double tickLineWidth = 1.0; - // We need a pair of layers for the graphics and drop-shadows, but it's probably not // worth adding more layers to the enum. #define LAYER_RULER LAYER_SELECT_OVERLAY @@ -66,13 +63,14 @@ static void drawCursorStrings( int aLayer, KIGFX::VIEW* aView, const VECTOR2D& a } -static double getTickLineWidth( KIGFX::GAL* aGal, int aLayer ) +static double getTickLineWidth( const TEXT_DIMS& textDims, int aLayer ) { - if( aLayer == LAYER_RULER_SHADOWS ) - return ( tickLineWidth * 3.0 ) / aGal->GetWorldScale(); - else - return tickLineWidth / aGal->GetWorldScale(); + double width = textDims.StrokeWidth * 0.8; + if( aLayer == LAYER_RULER_SHADOWS ) + width += textDims.ShadowWidth; + + return width; } @@ -124,40 +122,6 @@ static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace, EDA } -static wxString FormatRulerNumber( double aVal, EDA_UNITS aUnits ) -{ - int precision = 3; - - // show a sane precision for the ruler tick marks, which don't need to be accurate down to - // the nanometre - switch( aUnits ) - { - case EDA_UNITS::MILLIMETRES: - precision = 2; // 10um - break; - - case EDA_UNITS::INCHES: - precision = 3; // 1mil - break; - - case EDA_UNITS::DEGREES: - precision = 1; // 0.1deg - break; - - case EDA_UNITS::PERCENT: - precision = 1; // 0.1% - break; - - case EDA_UNITS::UNSCALED: - break; - } - - const wxString fmtStr = wxString::Format( "%%.%df", precision ); - - return wxString::Format( fmtStr, To_User_Unit( aUnits, aVal ) ); -} - - /** * Draw labelled ticks on a line. Ticks are spaced according to a * maximum density. Miror ticks are not labelled. @@ -170,23 +134,24 @@ static wxString FormatRulerNumber( double aVal, EDA_UNITS aUnits ) void drawTicksAlongLine( int aLayer, KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR2D& aLine, double aMinorTickLen, EDA_UNITS aUnits ) { - VECTOR2D tickLine = aLine.Rotate( -M_PI_2 ); - double tickSpace; + VECTOR2D tickLine = aLine.Rotate( -M_PI_2 ); + double tickSpace; TICK_FORMAT tickF = getTickFormatForScale( aGal->GetWorldScale(), tickSpace, aUnits ); // number of ticks in whole ruler - int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace ); + int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace ); // work out which way up the tick labels go - double labelAngle = -tickLine.Angle(); - float textThickness = aGal->GetGlyphSize().x / 8; - float textOffset = 0; + TEXT_DIMS textDims = SetConstantGlyphHeight( aGal, -1 ); + double textThickness = textDims.StrokeWidth; + double labelAngle = -tickLine.Angle(); + double textOffset = 0; if( aLayer == LAYER_RULER_SHADOWS ) { // Drawing drop shadows - textOffset = textThickness; - textThickness *= 3.0; + textOffset = textDims.ShadowWidth; + textThickness += 2 * textDims.ShadowWidth; } double majorTickLen = aMinorTickLen * ( majorTickLengthFactor + 1 ); @@ -220,12 +185,12 @@ void drawTicksAlongLine( int aLayer, KIGFX::GAL* aGal, const VECTOR2D& aOrigin, length *= midTickLengthFactor; } - aGal->SetLineWidth( getTickLineWidth( aGal, aLayer ) ); + aGal->SetLineWidth( textThickness / 2 ); aGal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) ); if( drawLabel ) { - wxString label = FormatRulerNumber( tickSpace * i, aUnits ); + wxString label = DimensionLabel( "", tickSpace * i, aUnits, false ); aGal->SetLineWidth( textThickness ); aGal->StrokeText( label, tickPos + labelOffset, labelAngle ); } @@ -246,13 +211,14 @@ void drawTicksAlongLine( int aLayer, KIGFX::GAL* aGal, const VECTOR2D& aOrigin, void drawBacksideTicks( int aLayer, KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR2D& aLine, double aTickLen, int aNumDivisions ) { - const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions; + const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions; const VECTOR2D backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen ); + TEXT_DIMS textDims = SetConstantGlyphHeight( aGal, -1 ); for( int i = 0; i < aNumDivisions + 1; ++i ) { const VECTOR2D backTickPos = aOrigin + aLine.Resize( backTickSpace * i ); - aGal->SetLineWidth( getTickLineWidth( aGal, aLayer ) ); + aGal->SetLineWidth( getTickLineWidth( textDims, aLayer ) ); aGal->DrawLine( backTickPos, backTickPos + backTickVec ); } } @@ -287,7 +253,7 @@ void RULER_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { - KIGFX::GAL* gal = aView->GetGAL(); + KIGFX::GAL* gal = aView->GetGAL(); RENDER_SETTINGS* rs = aView->GetPainter()->GetSettings(); gal->PushDepth(); @@ -303,30 +269,19 @@ void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) ); if( aLayer == LAYER_RULER_SHADOWS ) - { - // Drawing drop-shadows - if( gal->GetStrokeColor().GetBrightness() > 0.5 ) - gal->SetStrokeColor( COLOR4D::BLACK.WithAlpha( 0.7 ) ); - else - gal->SetStrokeColor( COLOR4D::WHITE.WithAlpha( 0.7 ) ); - } + gal->SetStrokeColor( GetShadowColor( gal->GetStrokeColor() ) ); gal->ResetTextAttributes(); + TEXT_DIMS textDims = SetConstantGlyphHeight( gal ); // draw the main line from the origin to cursor - gal->SetLineWidth( getTickLineWidth( gal, aLayer ) ); + gal->SetLineWidth( getTickLineWidth( textDims, aLayer ) ); gal->DrawLine( origin, end ); VECTOR2D rulerVec( end - origin ); - // constant text size on screen - SetConstantGlyphHeight( *gal, 10.0 ); - drawCursorStrings( aLayer, aView, end, rulerVec, m_userUnits ); - // tick label size - SetConstantGlyphHeight( *gal, 9.0 ); - // basic tick size const double minorTickLen = 5.0 / gal->GetWorldScale(); diff --git a/common/preview_items/two_point_assistant.cpp b/common/preview_items/two_point_assistant.cpp index aeb9f3f34c..eca1460c19 100644 --- a/common/preview_items/two_point_assistant.cpp +++ b/common/preview_items/two_point_assistant.cpp @@ -87,9 +87,6 @@ void TWO_POINT_ASSISTANT::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const gal.ResetTextAttributes(); - // constant text size on screen - SetConstantGlyphHeight( gal, 12.0 ); - std::vector cursorStrings; if( m_shape == GEOM_SHAPE::SEGMENT ) diff --git a/common/richio.cpp b/common/richio.cpp index 9b81030686..0bb7a30bde 100644 --- a/common/richio.cpp +++ b/common/richio.cpp @@ -27,6 +27,7 @@ #include // HAVE_FGETC_NOLOCK #include +#include #include #include diff --git a/include/preview_items/preview_utils.h b/include/preview_items/preview_utils.h index 33ab6508cd..e37ec19ec4 100644 --- a/include/preview_items/preview_utils.h +++ b/include/preview_items/preview_utils.h @@ -36,6 +36,13 @@ class VIEW; namespace PREVIEW { +struct TEXT_DIMS +{ + double StrokeWidth; + double ShadowWidth; + double LinePitch; +}; + /** * Default alpha of "de-emphasised" features (like previously locked-in * lines @@ -47,16 +54,21 @@ double PreviewOverlayDeemphAlpha( bool aDeemph = true ); * Get a formatted string showing a dimension to a sane precision * with an optional prefix and unit suffix. */ -wxString DimensionLabel( const wxString& prefix, double aVal, EDA_UNITS aUnits ); +wxString DimensionLabel( const wxString& prefix, double aVal, EDA_UNITS aUnits, + bool aIncludeUnits = true ); /** * Set the GAL glyph height to a constant scaled value, so that it * always looks the same on screen * * @param aGal the GAL to draw on - * @param aHeight the height of the glyph, in pixels + * @param aRelativeSize similar to HTML font sizes; 0 will give a standard size while +1 etc. + * will give larger and -1 etc. will give smaller. + * @returns the text widths for the resulting glyph size. */ -void SetConstantGlyphHeight( KIGFX::GAL& aGal, double aHeight ); +TEXT_DIMS SetConstantGlyphHeight( KIGFX::GAL* aGal, int aRelativeSize = 0 ); + +COLOR4D GetShadowColor( COLOR4D aColor ); /** * Draw strings next to the cursor