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.

391 lines
12 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2011 jean-pierre.charras
  5. * Copyright (C) 2022 Mike Williams
  6. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include "pcb_reference_image.h"
  26. #include <base_units.h>
  27. #include <bitmaps.h>
  28. #include <board.h>
  29. #include <common.h>
  30. #include <core/mirror.h>
  31. #include <eda_draw_frame.h>
  32. #include <pcb_draw_panel_gal.h>
  33. #include <pcb_painter.h>
  34. #include <plotters/plotter.h>
  35. #include <geometry/geometry_utils.h>
  36. #include <geometry/shape_rect.h>
  37. #include <settings/color_settings.h>
  38. #include <trigo.h>
  39. #include <wx/mstream.h>
  40. using KIGFX::PCB_PAINTER;
  41. using KIGFX::PCB_RENDER_SETTINGS;
  42. PCB_REFERENCE_IMAGE::PCB_REFERENCE_IMAGE( BOARD_ITEM* aParent, const VECTOR2I& aPos,
  43. PCB_LAYER_ID aLayer ) :
  44. BOARD_ITEM( aParent, PCB_REFERENCE_IMAGE_T, aLayer ), m_referenceImage( pcbIUScale )
  45. {
  46. m_referenceImage.SetPosition( aPos );
  47. }
  48. PCB_REFERENCE_IMAGE::PCB_REFERENCE_IMAGE( const PCB_REFERENCE_IMAGE& aPCBBitmap ) :
  49. BOARD_ITEM( aPCBBitmap ), m_referenceImage( aPCBBitmap.m_referenceImage )
  50. {
  51. }
  52. PCB_REFERENCE_IMAGE::~PCB_REFERENCE_IMAGE()
  53. {
  54. }
  55. PCB_REFERENCE_IMAGE& PCB_REFERENCE_IMAGE::operator=( const BOARD_ITEM& aItem )
  56. {
  57. wxCHECK_MSG( Type() == aItem.Type(), *this,
  58. wxT( "Cannot assign object type " ) + aItem.GetClass() + wxT( " to type " )
  59. + GetClass() );
  60. if( &aItem != this )
  61. {
  62. BOARD_ITEM::operator=( aItem );
  63. const PCB_REFERENCE_IMAGE& refImg = static_cast<const PCB_REFERENCE_IMAGE&>( aItem );
  64. m_referenceImage = refImg.m_referenceImage;
  65. }
  66. return *this;
  67. }
  68. void PCB_REFERENCE_IMAGE::CopyFrom( const BOARD_ITEM* aOther )
  69. {
  70. wxCHECK( aOther && aOther->Type() == PCB_REFERENCE_IMAGE_T, /* void */ );
  71. *this = *static_cast<const PCB_REFERENCE_IMAGE*>( aOther );
  72. }
  73. EDA_ITEM* PCB_REFERENCE_IMAGE::Clone() const
  74. {
  75. return new PCB_REFERENCE_IMAGE( *this );
  76. }
  77. void PCB_REFERENCE_IMAGE::swapData( BOARD_ITEM* aItem )
  78. {
  79. wxCHECK_RET( aItem->Type() == PCB_REFERENCE_IMAGE_T,
  80. wxString::Format( wxT( "% object cannot swap data with %s object." ),
  81. GetClass(), aItem->GetClass() ) );
  82. PCB_REFERENCE_IMAGE* item = (PCB_REFERENCE_IMAGE*) aItem;
  83. std::swap( m_layer, item->m_layer );
  84. std::swap( m_isKnockout, item->m_isKnockout );
  85. std::swap( m_isLocked, item->m_isLocked );
  86. std::swap( m_flags, item->m_flags );
  87. std::swap( m_parent, item->m_parent );
  88. std::swap( m_forceVisible, item->m_forceVisible );
  89. m_referenceImage.SwapData( item->m_referenceImage );
  90. }
  91. double PCB_REFERENCE_IMAGE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
  92. {
  93. PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
  94. PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
  95. // All bitmaps are drawn on LAYER_DRAW_BITMAPS, but their
  96. // associated board layer controls their visibility.
  97. if( !GetBoard()->IsLayerVisible( m_layer ) )
  98. return LOD_HIDE;
  99. if( renderSettings->GetHighContrast()
  100. && renderSettings->m_ContrastModeDisplay == HIGH_CONTRAST_MODE::HIDDEN
  101. && !renderSettings->GetLayerIsHighContrast( m_layer ) )
  102. {
  103. return LOD_HIDE;
  104. }
  105. if( aView->IsLayerVisible( LAYER_DRAW_BITMAPS ) )
  106. return LOD_SHOW;
  107. return LOD_HIDE;
  108. }
  109. const BOX2I PCB_REFERENCE_IMAGE::GetBoundingBox() const
  110. {
  111. return m_referenceImage.GetBoundingBox();
  112. }
  113. std::shared_ptr<SHAPE> PCB_REFERENCE_IMAGE::GetEffectiveShape( PCB_LAYER_ID aLayer,
  114. FLASHING aFlash ) const
  115. {
  116. const BOX2I box = GetBoundingBox();
  117. return std::make_shared<SHAPE_RECT>( box.GetPosition(), box.GetWidth(), box.GetHeight() );
  118. }
  119. VECTOR2I PCB_REFERENCE_IMAGE::GetPosition() const
  120. {
  121. return m_referenceImage.GetPosition();
  122. }
  123. void PCB_REFERENCE_IMAGE::SetPosition( const VECTOR2I& aPos )
  124. {
  125. m_referenceImage.SetPosition( aPos );
  126. }
  127. void PCB_REFERENCE_IMAGE::Move( const VECTOR2I& aMoveVector )
  128. {
  129. // Defer to SetPosition to check the new position overflow
  130. SetPosition( GetPosition() + aMoveVector );
  131. }
  132. void PCB_REFERENCE_IMAGE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
  133. {
  134. m_referenceImage.Flip( aCentre, aFlipDirection );
  135. }
  136. void PCB_REFERENCE_IMAGE::Rotate( const VECTOR2I& aCenter, const EDA_ANGLE& aAngle )
  137. {
  138. m_referenceImage.Rotate( aCenter, aAngle );
  139. }
  140. #if defined( DEBUG )
  141. void PCB_REFERENCE_IMAGE::Show( int nestLevel, std::ostream& os ) const
  142. {
  143. // XML output:
  144. wxString s = GetClass();
  145. NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << m_referenceImage.GetPosition()
  146. << "/>\n";
  147. }
  148. #endif
  149. bool PCB_REFERENCE_IMAGE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
  150. {
  151. return KIGEOM::BoxHitTest( aPosition, GetBoundingBox(), aAccuracy );
  152. }
  153. bool PCB_REFERENCE_IMAGE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
  154. {
  155. return KIGEOM::BoxHitTest( aRect, GetBoundingBox(), aContained, aAccuracy );
  156. }
  157. BITMAPS PCB_REFERENCE_IMAGE::GetMenuImage() const
  158. {
  159. return BITMAPS::image;
  160. }
  161. void PCB_REFERENCE_IMAGE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
  162. std::vector<MSG_PANEL_ITEM>& aList )
  163. {
  164. aList.emplace_back( _( "Reference Image" ), wxEmptyString );
  165. aList.emplace_back( _( "PPI" ),
  166. wxString::Format( wxT( "%d " ), m_referenceImage.GetImage().GetPPI() ) );
  167. aList.emplace_back( _( "Scale" ),
  168. wxString::Format( wxT( "%f " ), m_referenceImage.GetImageScale() ) );
  169. aList.emplace_back( _( "Width" ),
  170. aFrame->MessageTextFromValue( m_referenceImage.GetSize().x ) );
  171. aList.emplace_back( _( "Height" ),
  172. aFrame->MessageTextFromValue( m_referenceImage.GetSize().y ) );
  173. aList.emplace_back( _( "Layer" ), LayerName( m_layer ) );
  174. }
  175. std::vector<int> PCB_REFERENCE_IMAGE::ViewGetLayers() const
  176. {
  177. return { BITMAP_LAYER_FOR( m_layer ) };
  178. }
  179. bool PCB_REFERENCE_IMAGE::operator==( const BOARD_ITEM& aBoardItem ) const
  180. {
  181. if( aBoardItem.Type() != Type() )
  182. return false;
  183. const PCB_REFERENCE_IMAGE& other = static_cast<const PCB_REFERENCE_IMAGE&>( aBoardItem );
  184. return *this == other;
  185. }
  186. bool PCB_REFERENCE_IMAGE::operator==( const PCB_REFERENCE_IMAGE& aOther ) const
  187. {
  188. if( m_layer != aOther.m_layer )
  189. return false;
  190. if( m_referenceImage != aOther.m_referenceImage )
  191. return false;
  192. return true;
  193. }
  194. double PCB_REFERENCE_IMAGE::Similarity( const BOARD_ITEM& aOther ) const
  195. {
  196. if( aOther.Type() != Type() )
  197. return 0.0;
  198. const PCB_REFERENCE_IMAGE& other = static_cast<const PCB_REFERENCE_IMAGE&>( aOther );
  199. double similarity = 1.0;
  200. if( m_layer != other.m_layer )
  201. similarity *= 0.9;
  202. similarity *= m_referenceImage.Similarity( other.m_referenceImage );
  203. return similarity;
  204. }
  205. int PCB_REFERENCE_IMAGE::GetTransformOriginOffsetX() const
  206. {
  207. return m_referenceImage.GetTransformOriginOffset().x;
  208. }
  209. void PCB_REFERENCE_IMAGE::SetTransformOriginOffsetX( int aX )
  210. {
  211. VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
  212. offset.x = aX;
  213. m_referenceImage.SetTransformOriginOffset( offset );
  214. }
  215. int PCB_REFERENCE_IMAGE::GetTransformOriginOffsetY() const
  216. {
  217. return m_referenceImage.GetTransformOriginOffset().y;
  218. }
  219. void PCB_REFERENCE_IMAGE::SetTransformOriginOffsetY( int aY )
  220. {
  221. VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
  222. offset.y = aY;
  223. m_referenceImage.SetTransformOriginOffset( offset );
  224. }
  225. double PCB_REFERENCE_IMAGE::GetImageScale() const
  226. {
  227. return m_referenceImage.GetImageScale();
  228. }
  229. void PCB_REFERENCE_IMAGE::SetImageScale( double aScale )
  230. {
  231. m_referenceImage.SetImageScale( aScale );
  232. }
  233. int PCB_REFERENCE_IMAGE::GetWidth() const
  234. {
  235. return m_referenceImage.GetImage().GetSize().x;
  236. }
  237. void PCB_REFERENCE_IMAGE::SetWidth( int aWidth )
  238. {
  239. m_referenceImage.SetWidth( aWidth );
  240. }
  241. int PCB_REFERENCE_IMAGE::GetHeight() const
  242. {
  243. return m_referenceImage.GetImage().GetSize().y;
  244. }
  245. void PCB_REFERENCE_IMAGE::SetHeight( int aHeight )
  246. {
  247. m_referenceImage.SetHeight( aHeight );
  248. }
  249. static struct PCB_REFERENCE_IMAGE_DESC
  250. {
  251. PCB_REFERENCE_IMAGE_DESC()
  252. {
  253. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  254. REGISTER_TYPE( PCB_REFERENCE_IMAGE );
  255. propMgr.InheritsAfter( TYPE_HASH( PCB_REFERENCE_IMAGE ), TYPE_HASH( BOARD_ITEM ) );
  256. propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ),
  257. new PROPERTY_ENUM<PCB_REFERENCE_IMAGE, PCB_LAYER_ID, BOARD_ITEM>( _HKI( "Associated Layer" ),
  258. &PCB_REFERENCE_IMAGE::SetLayer, &PCB_REFERENCE_IMAGE::GetLayer ) );
  259. const wxString groupImage = _HKI( "Image Properties" );
  260. propMgr.AddProperty( new PROPERTY<PCB_REFERENCE_IMAGE, double>( _HKI( "Scale" ),
  261. &PCB_REFERENCE_IMAGE::SetImageScale,
  262. &PCB_REFERENCE_IMAGE::GetImageScale ),
  263. groupImage );
  264. propMgr.AddProperty( new PROPERTY<PCB_REFERENCE_IMAGE, int>(
  265. _HKI( "Transform Offset X" ),
  266. &PCB_REFERENCE_IMAGE::SetTransformOriginOffsetX,
  267. &PCB_REFERENCE_IMAGE::GetTransformOriginOffsetX,
  268. PROPERTY_DISPLAY::PT_COORD, ORIGIN_TRANSFORMS::ABS_X_COORD ),
  269. groupImage );
  270. propMgr.AddProperty( new PROPERTY<PCB_REFERENCE_IMAGE, int>(
  271. _HKI( "Transform Offset Y" ),
  272. &PCB_REFERENCE_IMAGE::SetTransformOriginOffsetY,
  273. &PCB_REFERENCE_IMAGE::GetTransformOriginOffsetY,
  274. PROPERTY_DISPLAY::PT_COORD, ORIGIN_TRANSFORMS::ABS_Y_COORD ),
  275. groupImage );
  276. propMgr.AddProperty( new PROPERTY<PCB_REFERENCE_IMAGE, int>(
  277. _HKI( "Width" ),
  278. &PCB_REFERENCE_IMAGE::SetWidth,
  279. &PCB_REFERENCE_IMAGE::GetWidth,
  280. PROPERTY_DISPLAY::PT_COORD ),
  281. groupImage );
  282. propMgr.AddProperty( new PROPERTY<PCB_REFERENCE_IMAGE, int>(
  283. _HKI( "Height" ),
  284. &PCB_REFERENCE_IMAGE::SetHeight,
  285. &PCB_REFERENCE_IMAGE::GetHeight,
  286. PROPERTY_DISPLAY::PT_COORD ),
  287. groupImage );
  288. // For future use
  289. const wxString greyscale = _HKI( "Greyscale" );
  290. }
  291. } _PCB_REFERENCE_IMAGE_DESC;