← Back to team overview

kicad-developers team mailing list archive

Patch to draw bitmaps in GAL canvases

 

Hi, GAL gurus,

I wrote this fix that add the code to draw bitmaps that can be used in page layout editor and eeschema.
(Currently, this code is missing, and bitmaps used in page layout are shown in legacy canvas, but
not in GAL canvases)

I need a GAL guru to verify this patch (I am not a OpenGL or Cairo specialist).
I do not want to break something.

I am thinking the Cairo code is good.
In opengl canvas, I am using a "brute force" code to draw pixels as rectangles.
I tried other ways, but there did not work.

Thanks.

-- 
Jean-Pierre CHARRAS
From 7551efc7edb270752717f599b7b98f513f67eaac Mon Sep 17 00:00:00 2001
From: jean-pierre charras <jp.charras@xxxxxxxxxx>
Date: Wed, 6 Jun 2018 18:59:16 +0200
Subject: [PATCH 1/2] GAL canvases: add DrawBitmap(), using a basic brute force
 algo for OpenGL, and a optimized code for Cairo. In this fix the brute force
 means draw each pixel as a rectangle. It works fine, but could be optimized.

---
 common/gal/cairo/cairo_gal.cpp           | 56 ++++++++++++++++++++++++
 common/gal/opengl/opengl_gal.cpp         | 41 +++++++++++++++++
 common/worksheet_viewitem.cpp            | 13 ++++++
 include/gal/cairo/cairo_gal.h            |  3 ++
 include/gal/graphics_abstraction_layer.h |  6 +++
 include/gal/opengl/opengl_gal.h          |  3 ++
 include/worksheet_shape_builder.h        |  2 +-
 include/worksheet_viewitem.h             |  2 +
 8 files changed, 125 insertions(+), 1 deletion(-)

diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp
index 0f3efa3fc..53593c3cc 100644
--- a/common/gal/cairo/cairo_gal.cpp
+++ b/common/gal/cairo/cairo_gal.cpp
@@ -33,6 +33,7 @@
 #include <gal/cairo/cairo_compositor.h>
 #include <gal/definitions.h>
 #include <geometry/shape_poly_set.h>
+#include <bitmap_base.h>
 
 #include <limits>
 
@@ -347,6 +348,61 @@ void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControl
 }
 
 
+void CAIRO_GAL::DrawBitmap( const BITMAP_BASE& aBitmap )
+{
+    int ppi = aBitmap.GetPPI();
+    double worldIU_per_mm = 1/(worldUnitLength/2.54)/1000;
+    double pix_size_iu =  worldIU_per_mm * ( 25.4 / ppi );
+    int w = aBitmap.GetSizePixels().x;
+    int h = aBitmap.GetSizePixels().y;
+
+    cairo_save( currentContext );
+
+    // Set the pixel scaling factor:
+    cairo_scale( currentContext, pix_size_iu, pix_size_iu );
+    // The position of the bitmap is the bitmap center.
+    // move the draw origin to the top left bitmap corner:
+    cairo_translate( currentContext, -w/2, -h/2 );
+
+    cairo_new_path( currentContext );
+    cairo_surface_t *image;
+    image = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h );
+    cairo_surface_flush( image );
+
+    unsigned char* pix_buffer = cairo_image_surface_get_data( image );
+    // The pixel buffer of the initial bitmap:
+    auto bm_pix_buffer = (( BITMAP_BASE&)aBitmap).GetImageData();
+
+    // Copy the source bitmap to the cairo bitmap buffer.
+    // In cairo bitmap buffer, a RGB24 bitmap is a RGB pixel packed into a uint_32
+    // 24 low bits only are used.
+    for( int row = 0; row < h; row++ )
+    {
+        for( int col = 0; col < w; col++ )
+        {
+            // Build the RGB24 pixel:
+            uint32_t pixel = bm_pix_buffer->GetRed( col, row ) << 16;
+            pixel += bm_pix_buffer->GetGreen( col, row ) << 8;
+            pixel += bm_pix_buffer->GetBlue( col, row );
+
+            // Write the pixel to the cairo image buffer:
+            uint32_t* pix_ptr = (uint32_t*) pix_buffer;
+            *pix_ptr = pixel;
+            pix_buffer += 4;
+        }
+    }
+
+    cairo_surface_mark_dirty( image );
+    cairo_set_source_surface( currentContext, image, 0, 0 );
+    cairo_paint( currentContext );
+    cairo_surface_destroy( image );
+
+    isElementAdded = true;
+
+    cairo_restore( currentContext );
+}
+
+
 void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
 {
     screenSize = VECTOR2I( aWidth, aHeight );
diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index 041b40018..aedee1005 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -32,6 +32,7 @@
 #include <gl_context_mgr.h>
 #include <geometry/shape_poly_set.h>
 #include <text_utils.h>
+#include <bitmap_base.h>
 
 #include <macros.h>
 
@@ -899,6 +900,46 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro
 }
 
 
+void OPENGL_GAL::DrawBitmap( const BITMAP_BASE& aBitmap )
+{
+    int ppi = aBitmap.GetPPI();
+    double worldIU_per_mm = 1/(worldUnitLength/2.54)/1000;
+    double pix_size_iu =  worldIU_per_mm * ( 25.4 / ppi );
+
+    Save();
+
+    // Set the pixel scaling factor:
+    currentManager->Scale( pix_size_iu, pix_size_iu, 0 );
+    // The position of the bitmap is the bitmap center.
+    // move the draw origin to the top left bitmap corner:
+    currentManager->Translate( -aBitmap.GetSizePixels().x/2, -aBitmap.GetSizePixels().y/2, 0 );
+
+    isFillEnabled = true;
+    isStrokeEnabled = false;
+
+    // The pixel buffer of the initial bitmap:
+    auto bm_pix_buffer = (( BITMAP_BASE&)aBitmap).GetImageData();
+
+    for( int row = 0; row < aBitmap.GetSizePixels().y; row++ )
+    {
+        VECTOR2D pos( 0, row );
+
+        for( int col = 0; col < aBitmap.GetSizePixels().x; col++ )
+        {
+            pos.x = col;
+            SetFillColor( COLOR4D( bm_pix_buffer->GetRed( col, row )/255.0,
+                                   bm_pix_buffer->GetGreen( col, row )/255.0,
+                                   bm_pix_buffer->GetBlue( col, row )/255.0,
+                                   1.0 ) );
+            VECTOR2D end = pos + 1.0;   // Size of the rectangle = 1 pixel
+            DrawRectangle( pos, end );
+        }
+    }
+
+    Restore();
+}
+
+
 void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition,
                              double aRotationAngle )
 {
diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp
index 1a970157c..632946256 100644
--- a/common/worksheet_viewitem.cpp
+++ b/common/worksheet_viewitem.cpp
@@ -29,6 +29,7 @@
 
 #include <worksheet_viewitem.h>
 #include <worksheet_shape_builder.h>
+#include <worksheet_dataitem.h>
 #include <gal/graphics_abstraction_layer.h>
 #include <painter.h>
 #include <layers_id_colors_and_visibility.h>
@@ -119,6 +120,7 @@ void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, VIEW* aView ) const
             break;
 
         case WS_DRAW_ITEM_BASE::wsg_bitmap:
+            draw( static_cast<const WS_DRAW_ITEM_BITMAP*>( item ), gal );
             break;
         }
 
@@ -199,6 +201,17 @@ void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const
 }
 
 
+void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_BITMAP* aItem, GAL* aGal ) const
+{
+    aGal->Save();
+    VECTOR2D position = aItem->GetPosition();
+    aGal->Translate( position );
+    WORKSHEET_DATAITEM_BITMAP* parent = static_cast<WORKSHEET_DATAITEM_BITMAP*>( aItem->GetParent() );
+    aGal->DrawBitmap( *parent->m_ImageBitmap );
+    aGal->Restore();
+}
+
+
 void WORKSHEET_VIEWITEM::drawBorder( GAL* aGal ) const
 {
     VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h
index fad2fd428..7f515cf55 100644
--- a/include/gal/cairo/cairo_gal.h
+++ b/include/gal/cairo/cairo_gal.h
@@ -136,6 +136,9 @@ public:
     virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
                             const VECTOR2D& controlPointB, const VECTOR2D& endPoint ) override;
 
+    /// @copydoc GAL::DrawBitmap()
+    virtual void DrawBitmap( const BITMAP_BASE& aBitmap ) override;
+
     // --------------
     // Screen methods
     // --------------
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index b3d571a34..1cca778d1 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -41,6 +41,7 @@
 
 class SHAPE_LINE_CHAIN;
 class SHAPE_POLY_SET;
+class BITMAP_BASE;
 
 namespace KIGFX
 {
@@ -179,6 +180,11 @@ public:
     virtual void DrawCurve( const VECTOR2D& startPoint,    const VECTOR2D& controlPointA,
                             const VECTOR2D& controlPointB, const VECTOR2D& endPoint ) {};
 
+    /**
+     * @brief Draw a bitmap image.
+     */
+    virtual void DrawBitmap( const BITMAP_BASE& aBitmap ) {};
+
     // --------------
     // Screen methods
     // --------------
diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h
index 7ab14c3a6..a732fa8f6 100644
--- a/include/gal/opengl/opengl_gal.h
+++ b/include/gal/opengl/opengl_gal.h
@@ -149,6 +149,9 @@ public:
     virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
                             const VECTOR2D& controlPointB, const VECTOR2D& endPoint ) override;
 
+    /// @copydoc GAL::DrawBitmap()
+    virtual void DrawBitmap( const BITMAP_BASE& aBitmap ) override;
+
     /// @copydoc GAL::BitmapText()
     virtual void BitmapText( const wxString& aText, const VECTOR2D& aPosition,
                              double aRotationAngle ) override;
diff --git a/include/worksheet_shape_builder.h b/include/worksheet_shape_builder.h
index cd65ae6c0..c30f58fc8 100644
--- a/include/worksheet_shape_builder.h
+++ b/include/worksheet_shape_builder.h
@@ -361,7 +361,7 @@ public:
      */
     virtual bool HitTestStartPoint( const wxPoint& aPosition) override;
 
-    const wxPoint GetPosition() { return m_pos; }
+    const wxPoint GetPosition() const { return m_pos; }
 };
 
 /*
diff --git a/include/worksheet_viewitem.h b/include/worksheet_viewitem.h
index 2a6115e70..c2edb866d 100644
--- a/include/worksheet_viewitem.h
+++ b/include/worksheet_viewitem.h
@@ -39,6 +39,7 @@ class WS_DRAW_ITEM_LINE;
 class WS_DRAW_ITEM_RECT;
 class WS_DRAW_ITEM_POLYGON;
 class WS_DRAW_ITEM_TEXT;
+class WS_DRAW_ITEM_BITMAP;
 
 namespace KIGFX
 {
@@ -163,6 +164,7 @@ protected:
     void draw( const WS_DRAW_ITEM_RECT* aItem, GAL* aGal ) const;
     void draw( const WS_DRAW_ITEM_POLYGON* aItem, GAL* aGal ) const;
     void draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const;
+    void draw( const WS_DRAW_ITEM_BITMAP* aItem, GAL* aGal ) const;
 
     /// Draws a border that determines the page size.
     void drawBorder( GAL* aGal ) const;
-- 
2.17.0.windows.1


Follow ups