diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 2796cef8f9..1e8d154146 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2013-2024, 2024 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2013-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> @@ -277,10 +277,20 @@ bool EDA_DRAW_PANEL_GAL::DoRePaint() m_gal->SetGridColor( settings->GetGridColor() ); m_gal->SetCursorColor( settings->GetCursorColor() ); - m_gal->ClearScreen(); + // TODO: find why ClearScreen() must be called here in opengl mode + // and only if m_view->IsDirty() in Cairo mode to avoid display artifacts + // when moving the mouse cursor + if( m_backend == GAL_TYPE_OPENGL ) + m_gal->ClearScreen(); if( m_view->IsDirty() ) { + if( m_backend != GAL_TYPE_OPENGL // Already called in opengl + && m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) ) + { + m_gal->ClearScreen(); + } + m_view->ClearTargets(); // Grid has to be redrawn only when the NONCACHED target is redrawn diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index cd6f8f3d80..dfef4ee1e6 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de - * Copyright (C) 2012-2024 Kicad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012-2023 Kicad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017-2018 CERN * * @author Maciej Suminski <maciej.suminski@cern.ch> @@ -29,7 +29,6 @@ #include <wx/image.h> #include <wx/log.h> -#include <wx/rawbmp.h> #include <gal/cairo/cairo_gal.h> #include <gal/cairo/cairo_compositor.h> @@ -583,9 +582,6 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap, double alphaBlend ) void CAIRO_GAL_BASE::ResizeScreen( int aWidth, int aHeight ) { m_screenSize = VECTOR2I( aWidth, aHeight ); - - m_bitmapSize = VECTOR2I( std::ceil( m_screenSize.x * getScalingFactor() ), - std::ceil( m_screenSize.y * getScalingFactor() ) ); } @@ -597,9 +593,9 @@ void CAIRO_GAL_BASE::Flush() void CAIRO_GAL_BASE::ClearScreen() { - cairo_set_source_rgb( m_context, m_clearColor.r, m_clearColor.g, m_clearColor.b ); - cairo_rectangle( m_context, 0.0, 0.0, m_bitmapSize.x, m_bitmapSize.y ); - cairo_fill( m_context ); + cairo_set_source_rgb( m_currentContext, m_clearColor.r, m_clearColor.g, m_clearColor.b ); + cairo_rectangle( m_currentContext, 0.0, 0.0, m_screenSize.x, m_screenSize.y ); + cairo_fill( m_currentContext ); } @@ -1024,15 +1020,15 @@ void CAIRO_GAL_BASE::resetContext() m_imageSurfaces.clear(); + ClearScreen(); + // Compute the world <-> screen transformations ComputeWorldScreenMatrix(); - double sf = getScalingFactor(); - - cairo_matrix_init( &m_cairoWorldScreenMatrix, - m_worldScreenMatrix.m_data[0][0] * sf, m_worldScreenMatrix.m_data[1][0] * sf, - m_worldScreenMatrix.m_data[0][1] * sf, m_worldScreenMatrix.m_data[1][1] * sf, - m_worldScreenMatrix.m_data[0][2] * sf, m_worldScreenMatrix.m_data[1][2] * sf ); + cairo_matrix_init( &m_cairoWorldScreenMatrix, m_worldScreenMatrix.m_data[0][0], + m_worldScreenMatrix.m_data[1][0], m_worldScreenMatrix.m_data[0][1], + m_worldScreenMatrix.m_data[1][1], m_worldScreenMatrix.m_data[0][2], + m_worldScreenMatrix.m_data[1][2] ); // we work in screen-space coordinates and do the transforms outside. cairo_identity_matrix( m_context ); @@ -1340,10 +1336,8 @@ CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent, m_currentTarget = TARGET_NONCACHED; SetTarget( TARGET_NONCACHED ); - SetBackgroundStyle( wxBG_STYLE_PAINT ); - m_bitmapBuffer = nullptr; - m_wxBitmap = nullptr; + m_wxOutput = nullptr; m_parentWindow = aParent; m_mouseListener = aMouseListener; @@ -1382,6 +1376,10 @@ CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent, Bind( wxEVT_GESTURE_PAN, &CAIRO_GAL::skipGestureEvent, this ); SetSize( aParent->GetClientSize() ); + m_screenSize = ToVECTOR2I( aParent->GetClientSize() ); + + // Allocate memory for pixel storage + allocateBitmaps(); m_isInitialized = false; } @@ -1417,44 +1415,45 @@ void CAIRO_GAL::EndDrawing() // Now translate the raw context data from the format stored // by cairo into a format understood by wxImage. - int height = m_bitmapSize.y; + int height = m_screenSize.y; int stride = m_stride; unsigned char* srcRow = m_bitmapBuffer; - - wxNativePixelData dstData( *m_wxBitmap ); - wxNativePixelData::Iterator di( dstData ); + unsigned char* dst = m_wxOutput; for( int y = 0; y < height; y++ ) { - wxNativePixelData::Iterator rowStart = di; - - for( int x = 0; x < stride; x += 4, ++di ) + for( int x = 0; x < stride; x += 4 ) { const unsigned char* src = srcRow + x; #if defined( __BYTE_ORDER__ ) && ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) // XRGB - di.Red() = src[1]; - di.Green() = src[2]; - di.Blue() = src[3]; + dst[0] = src[1]; + dst[1] = src[2]; + dst[2] = src[3]; #else // BGRX - di.Red() = src[2]; - di.Green() = src[1]; - di.Blue() = src[0]; + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; #endif + dst += 3; } srcRow += stride; - - di = rowStart; - di.OffsetY( dstData, 1 ); } - deinitSurface(); + wxImage img( m_wxBufferWidth, m_screenSize.y, m_wxOutput, true ); + wxBitmap bmp( img ); + wxMemoryDC mdc( bmp ); + wxClientDC clientDC( this ); - Refresh(); // Trigger repaint + // Now it is the time to blit the mouse cursor + blitCursor( mdc ); + clientDC.Blit( 0, 0, m_screenSize.x, m_screenSize.y, &mdc, 0, 0, wxCOPY ); + + deinitSurface(); } @@ -1475,7 +1474,7 @@ void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight ) allocateBitmaps(); if( m_validCompositor ) - m_compositor->Resize( m_bitmapSize.x, m_bitmapSize.y ); + m_compositor->Resize( aWidth, aHeight ); m_validCompositor = false; @@ -1566,7 +1565,7 @@ void CAIRO_GAL::initSurface() return; m_surface = cairo_image_surface_create_for_data( m_bitmapBuffer, GAL_FORMAT, m_wxBufferWidth, - m_bitmapSize.y, m_stride ); + m_screenSize.y, m_stride ); m_context = cairo_create( m_surface ); @@ -1597,18 +1596,17 @@ void CAIRO_GAL::deinitSurface() void CAIRO_GAL::allocateBitmaps() { - m_wxBufferWidth = m_bitmapSize.x; + m_wxBufferWidth = m_screenSize.x; // Create buffer, use the system independent Cairo context backend m_stride = cairo_format_stride_for_width( GAL_FORMAT, m_wxBufferWidth ); - m_bufferSize = m_stride * m_bitmapSize.y; + m_bufferSize = m_stride * m_screenSize.y; wxASSERT( m_bitmapBuffer == nullptr ); m_bitmapBuffer = new unsigned char[m_bufferSize]; - wxASSERT( m_wxBitmap == nullptr ); - m_wxBitmap = new wxBitmap( m_wxBufferWidth, m_bitmapSize.y, 24 ); - m_wxBitmap->SetScaleFactor( getScalingFactor() ); + wxASSERT( m_wxOutput == nullptr ); + m_wxOutput = new unsigned char[m_wxBufferWidth * 3 * m_screenSize.y]; } @@ -1617,8 +1615,8 @@ void CAIRO_GAL::deleteBitmaps() delete[] m_bitmapBuffer; m_bitmapBuffer = nullptr; - delete m_wxBitmap; - m_wxBitmap = nullptr; + delete[] m_wxOutput; + m_wxOutput = nullptr; } @@ -1626,7 +1624,7 @@ void CAIRO_GAL::setCompositor() { // Recreate the compositor with the new Cairo context m_compositor.reset( new CAIRO_COMPOSITOR( &m_currentContext ) ); - m_compositor->Resize( m_bitmapSize.x, m_bitmapSize.y ); + m_compositor->Resize( m_screenSize.x, m_screenSize.y ); m_compositor->SetAntialiasingMode( m_options.cairo_antialiasing_mode ); // Prepare buffers @@ -1640,22 +1638,7 @@ void CAIRO_GAL::setCompositor() void CAIRO_GAL::onPaint( wxPaintEvent& aEvent ) { - // We should have the rendered image in m_wxBitmap after EDA_DRAW_PANEL_GAL::onPaint - - if( !m_wxBitmap ) - { - wxLogDebug( "CAIRO_GAL::onPaint null output bitmap buffer" ); - return; - } - - { - // Now it is the time to blit the mouse cursor - wxMemoryDC mdc( *m_wxBitmap ); - blitCursor( mdc ); - } - - wxPaintDC paintDC( this ); - paintDC.DrawBitmap( *m_wxBitmap, 0, 0 ); + PostPaint( aEvent ); } @@ -1699,12 +1682,6 @@ bool CAIRO_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) } -double CAIRO_GAL::getScalingFactor() -{ - return GetContentScaleFactor(); -}; - - bool CAIRO_GAL::SetNativeCursorStyle( KICURSOR aCursor, bool aHiDPI ) { // Store the current cursor type and get the wxCursor for it diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 1736d8af42..2e2438605e 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -2,7 +2,7 @@ * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de - * Copyright (C) 2012-2024 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017-2018 CERN * @author Maciej Suminski <maciej.suminski@cern.ch> * @@ -252,9 +252,6 @@ protected: const VECTOR2D xform( double x, double y ); // rotation, scale and offset const VECTOR2D xform( const VECTOR2D& aP ); // rotation, scale and offset - // Return the scaling factor for current window. - virtual double getScalingFactor() { return 1.0; } - /** * Transform according to the rotation from m_currentWorld2Screen transform matrix. * @@ -455,8 +452,6 @@ public: /// @copydoc GAL::EndDrawing() void EndDrawing() override; -protected: - /// Prepare Cairo surfaces for drawing void initSurface(); @@ -504,9 +499,6 @@ protected: ///< Cairo-specific update handlers bool updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions ) override; - ///< For HiDPI support - double getScalingFactor() override; - protected: // Compositor related variables std::shared_ptr<CAIRO_COMPOSITOR> m_compositor; ///< Object for layers compositing @@ -522,7 +514,7 @@ protected: wxEvtHandler* m_mouseListener; ///< Mouse listener wxEvtHandler* m_paintListener; ///< Paint listener unsigned int m_bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers - wxBitmap* m_wxBitmap; ///< Output buffer bitmap + unsigned char* m_wxOutput; ///< wxImage compatible buffer // Variables related to Cairo <-> wxWidgets unsigned char* m_bitmapBuffer; ///< Storage of the Cairo image diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index c4d1cb36c8..8b92fa7fcd 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -2,7 +2,7 @@ * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de - * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. * * Graphics Abstraction Layer (GAL) - base class * @@ -1060,8 +1060,8 @@ protected: GAL_DISPLAY_OPTIONS& m_options; UTIL::LINK m_observerLink; + std::stack<double> m_depthStack; ///< Stored depth values VECTOR2I m_screenSize; ///< Screen size in screen (wx logical) coordinates - VECTOR2I m_bitmapSize; ///< Bitmap size, in physical pixels double m_worldUnitLength; ///< The unit length of the world coordinates [inch] double m_screenDPI; ///< The dots per inch of the screen