You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
6.5 KiB

  1. /*
  2. * This program source code file is part of KICAD, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2019-2023 Kicad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <preview_items/preview_utils.h>
  20. #include <gal/graphics_abstraction_layer.h>
  21. #include <base_units.h>
  22. #include <gal/painter.h>
  23. #include <view/view.h>
  24. #include <gal/hidpi_gl_canvas.h>
  25. double KIGFX::PREVIEW::PreviewOverlayDeemphAlpha( bool aDeemph )
  26. {
  27. return aDeemph ? 0.5 : 1.0;
  28. }
  29. wxString KIGFX::PREVIEW::DimensionLabel( const wxString& prefix, double aVal,
  30. const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
  31. bool aIncludeUnits )
  32. {
  33. wxString str;
  34. if( prefix.size() )
  35. str << prefix << ": ";
  36. wxString fmtStr;
  37. // show a sane precision for the preview, which doesn't need to be accurate down to the
  38. // nanometre
  39. switch( aUnits )
  40. {
  41. case EDA_UNITS::MICROMETRES: fmtStr = wxT( "%.0f" ); break; // 1um
  42. case EDA_UNITS::MILLIMETRES: fmtStr = wxT( "%.3f" ); break; // 1um
  43. case EDA_UNITS::CENTIMETRES: fmtStr = wxT( "%.4f" ); break; // 1um
  44. case EDA_UNITS::MILS: fmtStr = wxT( "%.1f" ); break; // 0.1mil
  45. case EDA_UNITS::INCHES: fmtStr = wxT( "%.4f" ); break; // 0.1mil
  46. case EDA_UNITS::DEGREES: fmtStr = wxT( "%.1f" ); break; // 0.1deg
  47. case EDA_UNITS::PERCENT: fmtStr = wxT( "%.1f" ); break; // 0.1%
  48. case EDA_UNITS::UNSCALED: fmtStr = wxT( "%f" ); break;
  49. }
  50. str << wxString::Format( fmtStr, EDA_UNIT_UTILS::UI::ToUserUnit( aIuScale, aUnits, aVal ) );
  51. if( aIncludeUnits )
  52. str << EDA_UNIT_UTILS::GetText( aUnits );
  53. return str;
  54. }
  55. KIGFX::PREVIEW::TEXT_DIMS KIGFX::PREVIEW::GetConstantGlyphHeight( KIGFX::GAL* aGal,
  56. int aRelativeSize )
  57. {
  58. constexpr double aspectRatio = 1.0;
  59. constexpr double hdpiSizes[] = { 7, 8, 9, 11, 13, 14, 16 };
  60. constexpr double sizes[] = { 8, 10, 12, 14, 15, 16, 18 };
  61. double height;
  62. double thicknessFactor;
  63. double shadowFactor;
  64. double linePitchFactor;
  65. HIDPI_GL_CANVAS* canvas = dynamic_cast<HIDPI_GL_CANVAS*>( aGal );
  66. if( canvas && canvas->GetScaleFactor() > 1 )
  67. {
  68. height = hdpiSizes[ 3 + aRelativeSize ];
  69. thicknessFactor = 0.15;
  70. shadowFactor = 0.10;
  71. linePitchFactor = 1.7;
  72. }
  73. else
  74. {
  75. height = sizes[ 3 + aRelativeSize ];
  76. thicknessFactor = 0.20;
  77. shadowFactor = 0.15;
  78. linePitchFactor = 1.9;
  79. }
  80. height /= aGal->GetWorldScale();
  81. TEXT_DIMS textDims;
  82. textDims.GlyphSize = VECTOR2I( height * aspectRatio, height );
  83. textDims.StrokeWidth = height * thicknessFactor;
  84. textDims.ShadowWidth = height * shadowFactor;
  85. textDims.LinePitch = height * linePitchFactor;
  86. return textDims;
  87. }
  88. KIGFX::COLOR4D KIGFX::PREVIEW::GetShadowColor( const KIGFX::COLOR4D& aColor )
  89. {
  90. if( aColor.GetBrightness() > 0.5 )
  91. return COLOR4D::BLACK;
  92. else
  93. return COLOR4D::WHITE;
  94. }
  95. void KIGFX::PREVIEW::DrawTextNextToCursor( KIGFX::VIEW* aView, const VECTOR2D& aCursorPos,
  96. const VECTOR2D& aTextQuadrant,
  97. const std::vector<wxString>& aStrings,
  98. bool aDrawingDropShadows )
  99. {
  100. KIGFX::GAL* gal = aView->GetGAL();
  101. KIFONT::FONT* font = KIFONT::FONT::GetFont();
  102. // constant text size on screen
  103. TEXT_DIMS textDims = GetConstantGlyphHeight( gal );
  104. TEXT_ATTRIBUTES textAttrs;
  105. // radius string goes on the right of the cursor centre line with a small horizontal
  106. // offset (enough to keep clear of a system cursor if present)
  107. VECTOR2D textPos = aCursorPos;
  108. bool viewFlipped = gal->IsFlippedX();
  109. // if the text goes above the cursor, shift it up
  110. if( aTextQuadrant.y > 0 )
  111. textPos.y -= textDims.LinePitch * ( aStrings.size() + 1 );
  112. if( aTextQuadrant.x < 0 )
  113. {
  114. if( viewFlipped )
  115. textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT;
  116. else
  117. textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
  118. textPos.x += 15.0 / gal->GetWorldScale();
  119. }
  120. else
  121. {
  122. if( viewFlipped )
  123. textAttrs.m_Halign = GR_TEXT_H_ALIGN_LEFT;
  124. else
  125. textAttrs.m_Halign = GR_TEXT_H_ALIGN_RIGHT;
  126. textPos.x -= 15.0 / gal->GetWorldScale();
  127. }
  128. // text is left (or right) aligned, so a shadow text need a small offset to be draw
  129. // around the basic text
  130. int shadowXoffset = aDrawingDropShadows ? textDims.ShadowWidth : 0;
  131. // Due to the fact a shadow text is drawn left or right aligned,
  132. // it needs an offset = shadowWidth/2 to be drawn at the same place as normal text
  133. // But for some reason we need to slightly modify this offset
  134. // for a better look for KiCad font (better alignment of shadow shape)
  135. const float adjust = 1.2f; // Value chosen after tests
  136. shadowXoffset *= adjust;
  137. if( ( textAttrs.m_Halign == GR_TEXT_H_ALIGN_LEFT ) != viewFlipped )
  138. textPos.x -= shadowXoffset;
  139. else
  140. textPos.x += shadowXoffset;
  141. gal->SetStrokeColor( aView->GetPainter()->GetSettings()->GetLayerColor( LAYER_AUX_ITEMS ) );
  142. textAttrs.m_Mirrored = viewFlipped; // Prevent text flipping when view is flipped
  143. textAttrs.m_Size = textDims.GlyphSize;
  144. textAttrs.m_StrokeWidth = textDims.StrokeWidth;
  145. gal->SetIsFill( false );
  146. gal->SetIsStroke( true );
  147. if( aDrawingDropShadows )
  148. {
  149. textAttrs.m_StrokeWidth = textDims.StrokeWidth + ( 2 * textDims.ShadowWidth );
  150. gal->SetStrokeColor( GetShadowColor( gal->GetStrokeColor() ) );
  151. }
  152. // write strings top-to-bottom
  153. for( const wxString& str : aStrings )
  154. {
  155. textPos.y += textDims.LinePitch;
  156. font->Draw( gal, str, textPos, textAttrs, KIFONT::METRICS::Default() );
  157. }
  158. }