2017-03-09 09:09:13 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
|
|
|
*
|
2023-06-23 08:32:23 +00:00
|
|
|
* Copyright (C) 2019-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
2017-03-09 09:09:13 +00:00
|
|
|
*
|
2019-07-02 13:28:37 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
* option) any later version.
|
2017-03-09 09:09:13 +00:00
|
|
|
*
|
2019-07-02 13:28:37 +00:00
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
2017-03-09 09:09:13 +00:00
|
|
|
*
|
2019-07-02 13:28:37 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
2017-03-09 09:09:13 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <preview_items/preview_utils.h>
|
|
|
|
#include <gal/graphics_abstraction_layer.h>
|
|
|
|
#include <base_units.h>
|
2023-09-07 00:23:19 +00:00
|
|
|
#include <gal/painter.h>
|
2017-08-04 12:43:02 +00:00
|
|
|
#include <view/view.h>
|
2020-10-01 10:48:50 +00:00
|
|
|
#include <gal/hidpi_gl_canvas.h>
|
2017-03-09 09:09:13 +00:00
|
|
|
|
|
|
|
double KIGFX::PREVIEW::PreviewOverlayDeemphAlpha( bool aDeemph )
|
|
|
|
{
|
|
|
|
return aDeemph ? 0.5 : 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-16 04:38:10 +00:00
|
|
|
wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal,
|
|
|
|
const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
|
2020-10-01 10:48:50 +00:00
|
|
|
bool aIncludeUnits )
|
2017-03-09 09:09:13 +00:00
|
|
|
{
|
2020-10-01 10:48:50 +00:00
|
|
|
wxString str;
|
|
|
|
|
|
|
|
if( prefix.size() )
|
|
|
|
str << prefix << ": ";
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
wxString fmtStr;
|
|
|
|
|
|
|
|
// show a sane precision for the preview, which doesn't need to be accurate down to the
|
|
|
|
// nanometre
|
2017-03-09 09:09:13 +00:00
|
|
|
switch( aUnits )
|
|
|
|
{
|
2023-11-17 09:10:28 +00:00
|
|
|
case EDA_UNITS::MICROMETRES: fmtStr = wxT( "%.1f" ); break; // 0.1um
|
2020-10-01 10:48:50 +00:00
|
|
|
case EDA_UNITS::MILLIMETRES: fmtStr = wxT( "%.3f" ); break; // 1um
|
2023-11-17 09:10:28 +00:00
|
|
|
case EDA_UNITS::CENTIMETRES: fmtStr = wxT( "%.4f" ); break; // 1um
|
2020-10-02 20:51:24 +00:00
|
|
|
case EDA_UNITS::MILS: fmtStr = wxT( "%.1f" ); break; // 0.1mil
|
2020-10-01 10:48:50 +00:00
|
|
|
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;
|
|
|
|
}
|
2019-02-22 19:47:55 +00:00
|
|
|
|
2022-09-16 04:38:10 +00:00
|
|
|
str << wxString::Format( fmtStr, EDA_UNIT_UTILS::UI::ToUserUnit( aIuScale, aUnits, aVal ) );
|
2019-02-22 19:47:55 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
if( aIncludeUnits )
|
2022-09-19 09:25:20 +00:00
|
|
|
str << EDA_UNIT_UTILS::GetText( aUnits );
|
2019-02-22 19:47:55 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
return str;
|
|
|
|
}
|
2019-07-02 00:30:05 +00:00
|
|
|
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2022-01-11 13:47:21 +00:00
|
|
|
KIGFX::PREVIEW::TEXT_DIMS KIGFX::PREVIEW::GetConstantGlyphHeight( KIGFX::GAL* aGal,
|
2020-10-01 10:48:50 +00:00
|
|
|
int aRelativeSize )
|
|
|
|
{
|
2022-01-11 13:47:21 +00:00
|
|
|
constexpr double aspectRatio = 1.0;
|
2020-10-01 10:48:50 +00:00
|
|
|
constexpr double hdpiSizes[] = { 8, 9, 11, 13, 15 };
|
|
|
|
constexpr double sizes[] = { 10, 12, 14, 16, 18 };
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
double height;
|
|
|
|
double thicknessFactor;
|
|
|
|
double shadowFactor;
|
|
|
|
double linePitchFactor;
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
HIDPI_GL_CANVAS* canvas = dynamic_cast<HIDPI_GL_CANVAS*>( aGal );
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
height /= aGal->GetWorldScale();
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
TEXT_DIMS textDims;
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2022-01-11 13:47:21 +00:00
|
|
|
textDims.GlyphSize = VECTOR2I( height * aspectRatio, height );
|
|
|
|
textDims.StrokeWidth = height * thicknessFactor;
|
|
|
|
textDims.ShadowWidth = height * shadowFactor;
|
|
|
|
textDims.LinePitch = height * linePitchFactor;
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
return textDims;
|
2017-03-09 09:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-26 17:28:37 +00:00
|
|
|
KIGFX::COLOR4D KIGFX::PREVIEW::GetShadowColor( const KIGFX::COLOR4D& aColor )
|
2017-03-09 09:09:13 +00:00
|
|
|
{
|
2020-10-01 10:48:50 +00:00
|
|
|
if( aColor.GetBrightness() > 0.5 )
|
|
|
|
return COLOR4D::BLACK;
|
|
|
|
else
|
|
|
|
return COLOR4D::WHITE;
|
2017-03-09 09:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-24 02:02:21 +00:00
|
|
|
void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& aCursorPos,
|
|
|
|
const VECTOR2D& aTextQuadrant,
|
2020-09-30 19:02:30 +00:00
|
|
|
const std::vector<wxString>& aStrings,
|
|
|
|
bool aDrawingDropShadows )
|
2017-03-09 09:09:13 +00:00
|
|
|
{
|
2020-10-01 10:48:50 +00:00
|
|
|
KIGFX::GAL* gal = aView->GetGAL();
|
2022-01-11 13:47:21 +00:00
|
|
|
KIFONT::FONT* font = KIFONT::FONT::GetFont();
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-01 10:48:50 +00:00
|
|
|
// constant text size on screen
|
2022-01-11 13:47:21 +00:00
|
|
|
TEXT_DIMS textDims = GetConstantGlyphHeight( gal );
|
|
|
|
TEXT_ATTRIBUTES textAttrs;
|
2020-10-01 10:48:50 +00:00
|
|
|
|
|
|
|
// 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;
|
2017-03-09 09:09:13 +00:00
|
|
|
|
2020-10-10 22:04:11 +00:00
|
|
|
bool viewFlipped = gal->IsFlippedX();
|
2020-10-10 06:46:38 +00:00
|
|
|
|
2017-03-09 09:09:13 +00:00
|
|
|
// if the text goes above the cursor, shift it up
|
|
|
|
if( aTextQuadrant.y > 0 )
|
2020-10-01 10:48:50 +00:00
|
|
|
textPos.y -= textDims.LinePitch * ( aStrings.size() + 1 );
|
2017-03-09 09:09:13 +00:00
|
|
|
|
|
|
|
if( aTextQuadrant.x < 0 )
|
|
|
|
{
|
2020-10-10 22:04:11 +00:00
|
|
|
if( viewFlipped )
|
2022-01-11 13:47:21 +00:00
|
|
|
textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT;
|
2020-10-10 06:46:38 +00:00
|
|
|
else
|
2022-01-11 13:47:21 +00:00
|
|
|
textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
|
2020-10-10 06:46:38 +00:00
|
|
|
|
2017-08-04 12:43:02 +00:00
|
|
|
textPos.x += 15.0 / gal->GetWorldScale();
|
2017-03-09 09:09:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-10 22:04:11 +00:00
|
|
|
if( viewFlipped )
|
2022-01-11 13:47:21 +00:00
|
|
|
textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
|
2020-10-10 06:46:38 +00:00
|
|
|
else
|
2022-01-11 13:47:21 +00:00
|
|
|
textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT;
|
2020-10-10 06:46:38 +00:00
|
|
|
|
2017-08-04 12:43:02 +00:00
|
|
|
textPos.x -= 15.0 / gal->GetWorldScale();
|
2017-03-09 09:09:13 +00:00
|
|
|
}
|
|
|
|
|
2023-06-22 11:20:47 +00:00
|
|
|
// text is left (or right) aligned, so a shadow text need a small offset to be draw
|
|
|
|
// around the basic text
|
|
|
|
int shadowXoffset = aDrawingDropShadows ? textDims.ShadowWidth : 0;
|
|
|
|
|
2023-06-23 08:32:23 +00:00
|
|
|
// Due to the fact a shadow text is drawn left or right aligned,
|
|
|
|
// it needs an offset = shadowWidth/2 to be drawn at the same place as normal text
|
|
|
|
// But for some reason we need to slightly modify this offset
|
|
|
|
// for a better look for KiCad font (better alignment of shadow shape)
|
|
|
|
const float adjust = 1.2f; // Value chosen after tests
|
|
|
|
shadowXoffset *= adjust;
|
|
|
|
|
2023-06-22 11:20:47 +00:00
|
|
|
if( ( textAttrs.m_Halign == GR_TEXT_H_ALIGN_LEFT ) != viewFlipped )
|
|
|
|
textPos.x -= shadowXoffset;
|
|
|
|
else
|
|
|
|
textPos.x += shadowXoffset;
|
|
|
|
|
2022-01-11 13:47:21 +00:00
|
|
|
gal->SetStrokeColor( aView->GetPainter()->GetSettings()->GetLayerColor( LAYER_AUX_ITEMS ) );
|
|
|
|
textAttrs.m_Mirrored = viewFlipped; // Prevent text flipping when view is flipped
|
|
|
|
textAttrs.m_Size = textDims.GlyphSize;
|
|
|
|
textAttrs.m_StrokeWidth = textDims.StrokeWidth;
|
2022-07-15 18:52:29 +00:00
|
|
|
gal->SetIsFill( false );
|
|
|
|
gal->SetIsStroke( true );
|
2020-09-30 19:02:30 +00:00
|
|
|
|
|
|
|
if( aDrawingDropShadows )
|
|
|
|
{
|
2022-01-11 13:47:21 +00:00
|
|
|
textAttrs.m_StrokeWidth = textDims.StrokeWidth + ( 2 * textDims.ShadowWidth );
|
2020-10-01 10:48:50 +00:00
|
|
|
gal->SetStrokeColor( GetShadowColor( gal->GetStrokeColor() ) );
|
2020-09-30 19:02:30 +00:00
|
|
|
}
|
|
|
|
|
2017-03-09 09:09:13 +00:00
|
|
|
// write strings top-to-bottom
|
2020-09-30 19:02:30 +00:00
|
|
|
for( const wxString& str : aStrings )
|
2017-03-09 09:09:13 +00:00
|
|
|
{
|
2020-10-01 10:48:50 +00:00
|
|
|
textPos.y += textDims.LinePitch;
|
2023-08-06 19:20:53 +00:00
|
|
|
font->Draw( gal, str, textPos, textAttrs, KIFONT::METRICS::Default() );
|
2017-03-09 09:09:13 +00:00
|
|
|
}
|
|
|
|
}
|