Commit e262b321 authored by Maciej Suminski's avatar Maciej Suminski

Introduction of Graphics Abstraction Layer based rendering for pcbnew.

New classes:
    - VIEW - represents view that is seen by user, takes care of layer ordering & visibility and how it is displayed (which location, how much zoomed, etc.)
    - VIEW_ITEM - Base class for every item that can be displayed on VIEW (the biggest change is that now it may be necessary to override ViewBBox & ViewGetLayers method for derived classes).
    - EDA_DRAW_PANEL_GAL - Inherits after EDA_DRAW_PANEL, displays VIEW output, right now it is not editable (in opposite to usual EDA_DRAW_PANEL).
    - GAL/OPENGL_GAL/CAIRO_GAL - Base Graphics Abstraction Layer class + two different flavours (Cairo is not fully supported yet), that offers methods to draw primitives using different libraries.
    - WX_VIEW_CONTROLS - Controller for VIEW, handles user events, allows zooming, panning, etc.
    - PAINTER/PCB_PAINTER - Classes that uses GAL interface to draw items (as you may have already guessed - PCB_PAINTER is a class for drawing PCB specific object, PAINTER is an abstract class). Its methods are invoked by VIEW, when an item has to be drawn. To display a new type of item - you need to implement draw(ITEM_TYPE*) method that draws it using GAL methods.
    - STROKE_FONT - Implements stroke font drawing using GAL methods.
                          
Most important changes to Kicad original code:
    * EDA_ITEM now inherits from VIEW_ITEM, which is a base class for all drawable objects.
    * EDA_DRAW_FRAME contains both usual EDA_DRAW_PANEL and new EDA_DRAW_PANEL_GAL, that can be switched anytime.
    * There are some new layers for displaying multilayer pads, vias & pads holes (these are not shown yet on the right sidebar in pcbnew)
    * Display order of layers is different than in previous versions (if you are curious - you may check m_galLayerOrder@pcbnew/basepcbframe.cpp). Preserving usual order would result in not very natural display, such as showing silkscreen texts on the bottom.
    * Introduced new hotkey (Alt+F12) and new menu option (View->Switch canvas) for switching canvas during runtime.
    * Some of classes (mostly derived from BOARD_ITEM) now includes ViewBBox & ViewGetLayers methods.
    * Removed tools/class_painter.h, as now it is extended and included in source code.
                         
Build changes:
    * GAL-based rendering option is turned on by a new compilation CMake option KICAD_GAL.
    * When compiling with CMake option KICAD_GAL=ON, GLEW and Cairo libraries are required.
    * GAL-related code is compiled into a static library (common/libgal).
    * Build with KICAD_GAL=OFF should not need any new libraries and should come out as a standard version of Kicad
                            
Currently most of items in pcbnew can be displayed using OpenGL (to be done are DIMENSIONS and MARKERS).
More details about GAL can be found in: http://www.ohwr.org/attachments/1884/view-spec.pdf
parent ef2c9406
...@@ -57,6 +57,10 @@ option(KICAD_SCRIPTING_WXPYTHON ...@@ -57,6 +57,10 @@ option(KICAD_SCRIPTING_WXPYTHON
"set this option ON to build wxpython implementation for wx interface building in python and py.shell" "set this option ON to build wxpython implementation for wx interface building in python and py.shell"
) )
option(KICAD_GAL
"set this option ON to build KICAD using Graphics Abstraction Layer as a rendering backend"
)
# when option KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES is enabled: # when option KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES is enabled:
# PYTHON_EXECUTABLE can be defined when invoking cmake # PYTHON_EXECUTABLE can be defined when invoking cmake
# ( use -DPYTHON_EXECUTABLE=<python path>/python.exe or python2 ) # ( use -DPYTHON_EXECUTABLE=<python path>/python.exe or python2 )
...@@ -189,6 +193,10 @@ if(USE_WX_GRAPHICS_CONTEXT) ...@@ -189,6 +193,10 @@ if(USE_WX_GRAPHICS_CONTEXT)
add_definitions(-DUSE_WX_GRAPHICS_CONTEXT) add_definitions(-DUSE_WX_GRAPHICS_CONTEXT)
endif() endif()
if(KICAD_GAL)
add_definitions(-DKICAD_GAL)
endif()
# Allow user to override the default settings for adding images to menu items. By default # Allow user to override the default settings for adding images to menu items. By default
# images in menu items are enabled on all platforms except OSX. This can be over ridden by # images in menu items are enabled on all platforms except OSX. This can be over ridden by
# defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior. # defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior.
...@@ -257,6 +265,20 @@ add_definitions(-DWX_COMPATIBILITY) ...@@ -257,6 +265,20 @@ add_definitions(-DWX_COMPATIBILITY)
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
check_find_package_result(OPENGL_FOUND "OpenGL") check_find_package_result(OPENGL_FOUND "OpenGL")
if(KICAD_GAL)
#####################
# Find GLEW library #
#####################
find_package(GLEW)
check_find_package_result(GLEW_FOUND "GLEW")
######################
# Find Cairo library #
######################
find_package(Cairo 1.8.1 QUIET)
check_find_package_result(CAIRO_FOUND "Cairo")
endif(KICAD_GAL)
###################### ######################
# Find Boost library # # Find Boost library #
###################### ######################
......
...@@ -4,12 +4,29 @@ include_directories( ...@@ -4,12 +4,29 @@ include_directories(
./dialogs ./dialogs
./dialog_about ./dialog_about
${Boost_INCLUDE_DIR} ${Boost_INCLUDE_DIR}
${CAIRO_INCLUDE_DIR}
../3d-viewer ../3d-viewer
../pcbnew ../pcbnew
../polygon ../polygon
${INC_AFTER} ${INC_AFTER}
) )
if(KICAD_GAL)
set(GAL_SRCS
drawpanel_gal.cpp
painter.cpp
gal/graphics_abstraction_layer.cpp
gal/stroke_font.cpp
gal/color4d.cpp
gal/opengl/opengl_gal.cpp
gal/opengl/shader.cpp
gal/cairo/cairo_gal.cpp
view/wx_view_controls.cpp
)
add_library(gal STATIC ${GAL_SRCS})
endif(KICAD_GAL)
set(COMMON_ABOUT_DLG_SRCS set(COMMON_ABOUT_DLG_SRCS
dialog_about/AboutDialog_main.cpp dialog_about/AboutDialog_main.cpp
dialog_about/dialog_about.cpp dialog_about/dialog_about.cpp
...@@ -82,6 +99,14 @@ set(COMMON_SRCS ...@@ -82,6 +99,14 @@ set(COMMON_SRCS
zoom.cpp zoom.cpp
) )
if(KICAD_GAL)
set(COMMON_SRCS
${COMMON_SRCS}
view/view.cpp
view/view_item.cpp
)
endif(KICAD_GAL)
add_library(common STATIC ${COMMON_SRCS}) add_library(common STATIC ${COMMON_SRCS})
set(PCB_COMMON_SRCS set(PCB_COMMON_SRCS
...@@ -131,6 +156,12 @@ set(PCB_COMMON_SRCS ...@@ -131,6 +156,12 @@ set(PCB_COMMON_SRCS
fp_lib_table.cpp fp_lib_table.cpp
) )
if(KICAD_GAL)
set(PCB_COMMON_SRCS
${PCB_COMMON_SRCS}
../pcbnew/pcb_painter.cpp
)
endif(KICAD_GAL)
# add -DPCBNEW to compilation of these PCBNEW sources # add -DPCBNEW to compilation of these PCBNEW sources
set_source_files_properties( ${PCB_COMMON_SRCS} PROPERTIES set_source_files_properties( ${PCB_COMMON_SRCS} PROPERTIES
......
...@@ -222,6 +222,22 @@ EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem ) ...@@ -222,6 +222,22 @@ EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem )
} }
const BOX2I EDA_ITEM::ViewBBox() const
{
// Basic fallback
return BOX2I( VECTOR2I( GetBoundingBox().GetOrigin() ),
VECTOR2I( GetBoundingBox().GetSize() ) );
}
void EDA_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
{
// Basic fallback
aCount = 1;
aLayers[0] = 0;
}
#if defined(DEBUG) #if defined(DEBUG)
// A function that should have been in wxWidgets // A function that should have been in wxWidgets
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <macros.h> #include <macros.h>
#include <id.h> #include <id.h>
#include <class_drawpanel.h> #include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_base_screen.h> #include <class_base_screen.h>
#include <msgpanel.h> #include <msgpanel.h>
#include <wxstruct.h> #include <wxstruct.h>
...@@ -66,6 +67,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, EDA_BASE_FRAME ) ...@@ -66,6 +67,7 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, EDA_BASE_FRAME )
EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen ) EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen )
EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate ) EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate )
EVT_MENU_RANGE( ID_ZOOM_IN, ID_ZOOM_REDRAW, EDA_DRAW_FRAME::OnZoom ) EVT_MENU_RANGE( ID_ZOOM_IN, ID_ZOOM_REDRAW, EDA_DRAW_FRAME::OnZoom )
EVT_MENU( ID_SWITCH_CANVAS, EDA_DRAW_FRAME::OnZoom )
EVT_MENU_RANGE( ID_OFFCENTER_ZOOM_IN, ID_OFFCENTER_ZOOM_OUT, EDA_DRAW_FRAME::OnZoom ) EVT_MENU_RANGE( ID_OFFCENTER_ZOOM_IN, ID_OFFCENTER_ZOOM_OUT, EDA_DRAW_FRAME::OnZoom )
EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE, EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE,
EDA_DRAW_FRAME::OnZoom ) EDA_DRAW_FRAME::OnZoom )
...@@ -100,6 +102,8 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( wxWindow* aParent, ...@@ -100,6 +102,8 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( wxWindow* aParent,
m_HotkeysZoomAndGridList = NULL; m_HotkeysZoomAndGridList = NULL;
m_canvas = NULL; m_canvas = NULL;
m_galCanvas = NULL;
m_galCanvasActive = false;
m_messagePanel = NULL; m_messagePanel = NULL;
m_currentScreen = NULL; m_currentScreen = NULL;
m_toolId = ID_NO_TOOL_SELECTED; m_toolId = ID_NO_TOOL_SELECTED;
...@@ -937,3 +941,27 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU ) ...@@ -937,3 +941,27 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
screen->m_ScrollbarPos.x, screen->m_ScrollbarPos.x,
screen->m_ScrollbarPos.y, noRefresh ); screen->m_ScrollbarPos.y, noRefresh );
} }
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
{
if( !( aEnable ^ m_galCanvasActive ) )
return;
if( aEnable )
{
m_canvas->Hide();
m_galCanvas->Show();
m_galCanvas->Raise();
m_galCanvas->Refresh();
}
else
{
m_galCanvas->Hide();
m_canvas->Show();
m_canvas->Raise();
m_canvas->Refresh();
}
m_galCanvasActive = aEnable;
}
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <macros.h> #include <macros.h>
#include <id.h> #include <id.h>
#include <class_drawpanel.h> #include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_base_screen.h> #include <class_base_screen.h>
#include <wxstruct.h> #include <wxstruct.h>
...@@ -74,6 +75,9 @@ BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow ) ...@@ -74,6 +75,9 @@ BEGIN_EVENT_TABLE( EDA_DRAW_PANEL, wxScrolledWindow )
EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground ) EVT_ERASE_BACKGROUND( EDA_DRAW_PANEL::OnEraseBackground )
EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll ) EVT_SCROLLWIN( EDA_DRAW_PANEL::OnScroll )
EVT_ACTIVATE( EDA_DRAW_PANEL::OnActivate ) EVT_ACTIVATE( EDA_DRAW_PANEL::OnActivate )
#ifdef KICAD_GAL
EVT_SIZE( EDA_DRAW_PANEL::OnSize )
#endif
EVT_MENU_RANGE( ID_PAN_UP, ID_PAN_RIGHT, EDA_DRAW_PANEL::OnPan ) EVT_MENU_RANGE( ID_PAN_UP, ID_PAN_RIGHT, EDA_DRAW_PANEL::OnPan )
END_EVENT_TABLE() END_EVENT_TABLE()
...@@ -1377,6 +1381,18 @@ void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event ) ...@@ -1377,6 +1381,18 @@ void EDA_DRAW_PANEL::OnPan( wxCommandEvent& event )
} }
#ifdef KICAD_GAL
void EDA_DRAW_PANEL::OnSize( wxSizeEvent& SizeEv )
{
if( GetParent()->GetGalCanvas() != NULL )
{
GetParent()->GetGalCanvas()->SetPosition( GetPosition() );
GetParent()->GetGalCanvas()->SetSize( GetSize() );
}
}
#endif
void EDA_DRAW_PANEL::EndMouseCapture( int id, int cursor, const wxString& title, void EDA_DRAW_PANEL::EndMouseCapture( int id, int cursor, const wxString& title,
bool aCallEndFunc ) bool aCallEndFunc )
{ {
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/wx.h>
#include <wx/frame.h>
#include <wx/window.h>
#include <wx/event.h>
#include <wx/colour.h>
#include <wx/filefn.h>
#include <class_drawpanel_gal.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <pcb_painter.h>
#include <gal/graphics_abstraction_layer.h>
#include <gal/opengl/opengl_gal.h>
#include <gal/cairo/cairo_gal.h>
#define METRIC_UNIT_LENGTH (1e9)
void EDA_DRAW_PANEL_GAL::onPaint( wxEvent& event )
{
m_gal->BeginDrawing();
m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0, 0, 0, 1.0 ) );
m_gal->ClearScreen();
m_gal->SetGridOrigin( VECTOR2D( 0, 0 ) );
m_gal->SetGridOriginMarkerSize( 15 );
m_gal->SetGridSize( VECTOR2D( METRIC_UNIT_LENGTH / 10000.0, METRIC_UNIT_LENGTH / 10000.0 ) );
m_gal->SetGridDrawThreshold( 10 );
m_gal->SetLayerDepth( 0 );
m_gal->DrawGrid();
m_view->Redraw();
m_gal->EndDrawing();
m_gal->Flush();
}
void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent )
{
m_gal->ResizeScreen( aEvent.GetSize().x, aEvent.GetSize().y );
}
EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
const wxPoint& aPosition, const wxSize& aSize,
GalType aGalType ) :
wxWindow( aParentWindow, aWindowId, aPosition, aSize ),
m_screenSize( aSize.x, aSize.y ), m_parentFrame( aParentWindow )
{
m_gal = NULL;
m_view = NULL;
m_galShaderPath = std::string( ::wxGetCwd().mb_str() ) + "/../../gal/opengl/shader/";
SwitchBackend( aGalType, false );
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
// Initial display settings
m_gal->SetLookAtPoint( VECTOR2D( 0, 0 ) );
m_gal->SetZoomFactor( 1.0 );
m_gal->ComputeWorldScreenMatrix();
m_view = new KiGfx::VIEW( true );
m_view->SetGAL( m_gal );
// View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
// pad may be shown on pad, pad hole nad solder paste layers). There are usual copper layers
// (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
// silkscreen, pads, vias, etc.
for( int i = 0; i < TOTAL_LAYER_COUNT; i++ )
{
m_view->AddLayer( i );
}
m_viewControls = new KiGfx::WX_VIEW_CONTROLS( m_view, this );
m_painter = new KiGfx::PCB_PAINTER( m_gal );
m_view->SetPainter( m_painter );
// FIXME Cairo needs this to be uncommented to remove blinking on refreshing
// Connect( wxEVT_PAINT, wxEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
Connect(KiGfx::EVT_GAL_REDRAW, wxEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
Connect(wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this );
}
EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL()
{
if( m_painter )
delete m_painter;
if( m_viewControls )
delete m_viewControls;
if( m_view )
delete m_view;
if( m_gal )
delete m_gal;
}
void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType, bool aUseShaders )
{
if( m_gal )
delete m_gal;
switch( aGalType )
{
case GAL_TYPE_OPENGL:
m_gal = new KiGfx::OPENGL_GAL( this, this, this, aUseShaders );
static_cast<KiGfx::OPENGL_GAL*> (m_gal)->SetShaderPath( m_galShaderPath );
break;
case GAL_TYPE_CAIRO:
m_gal = new KiGfx::CAIRO_GAL( this, this, this );
break;
}
m_gal->SetWorldUnitLength( 1.0 / METRIC_UNIT_LENGTH * 2.54 ); // 1 inch in nanometers
m_gal->SetScreenDPI( 106 ); // Display resolution setting
m_gal->ComputeWorldScreenMatrix();
if( m_view )
m_view->SetGAL( m_gal );
}
This diff is collapsed.
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Graphics Abstraction Layer (GAL) - base class
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/log.h>
#include <gal/graphics_abstraction_layer.h>
#include <gal/definitions.h>
#include <gal/color4d.h>
using namespace KiGfx;
const wxEventType KiGfx::EVT_GAL_REDRAW = wxNewEventType();
GAL::GAL()
{
// Set the default values for the internal variables
SetIsFill( false );
SetIsStroke( true );
SetLineJoin( LINE_JOIN_ROUND );
SetLineCap( LINE_CAP_ROUND );
SetIsCursorEnabled( false );
SetZoomFactor( 1.0 );
SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
SetGridColor( COLOR4D( 1, 1, 1, 0.1 ) );
SetCoarseGrid( 5 );
SetLineWidth( 1.0 );
SetDepthRange( VECTOR2D( -2048, 2047 ) );
}
GAL::~GAL()
{
}
void GAL::DrawGrid()
{
// The grid consists of lines
// For the drawing the start points, end points and increments have to be calculated in world coordinates
VECTOR2D screenStartPoint( 0, 0 );
VECTOR2D screenEndPoint( screenSize.x, screenSize.y );
MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse();
VECTOR2D worldStartPoint = inverseMatrix * screenStartPoint;
VECTOR2D worldEndPoint = inverseMatrix * screenEndPoint;
// Compute grid variables
int gridStartX = round( worldStartPoint.x / gridSize.x );
int gridEndX = round( worldEndPoint.x / gridSize.x );
int gridStartY = round( worldStartPoint.y / gridSize.y );
int gridEndY = round( worldEndPoint.y / gridSize.y );
int gridScreenSizeDense = round( gridSize.x * worldScale );
int gridScreenSizeCoarse = round( gridSize.x * (double) gridTick * worldScale );
// Swap the coordinates, if they have not the right order
SWAP( gridEndX, <, gridStartX );
SWAP( gridEndY, <, gridStartY );
// Correct the index, else some lines are not correctly painted
gridStartX -= 1;
gridStartY -= 1;
gridEndX += 1;
gridEndY += 1;
double savedLineWidth = GetLineWidth();
COLOR4D savedColor = GetStrokeColor();
// Compute the line width of the grid
ComputeWorldScale();
double width = gridLineWidth / worldScale;
double doubleWidth = 2 * width;
// Set line width & color
SetLineWidth( width );
double origSize = (double) gridOriginMarkerSize / worldScale;
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
SetIsFill( false );
DrawLine( gridOrigin + VECTOR2D( -origSize, -origSize ), gridOrigin + VECTOR2D( origSize, origSize ) );
DrawLine( gridOrigin + VECTOR2D( -origSize, origSize ), gridOrigin + VECTOR2D( origSize, -origSize ) );
DrawCircle( gridOrigin, origSize * 0.7 );
SetStrokeColor( gridColor );
if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) < gridDrawThreshold )
return;
// Now draw the grid, every coarse grid line gets the double width
for( int j = gridStartY; j < gridEndY; j += 1 )
{
if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold )
{
SetLineWidth( doubleWidth );
}
else
{
SetLineWidth( width );
}
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold )
|| gridScreenSizeDense > gridDrawThreshold )
{
DrawGridLine( VECTOR2D( gridStartX * gridSize.x, j * gridSize.y ),
VECTOR2D( gridEndX * gridSize.x, j * gridSize.y ) );
}
}
for( int i = gridStartX; i < gridEndX; i += 1 )
{
if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold )
{
SetLineWidth( doubleWidth );
}
else
{
SetLineWidth( width );
}
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold )
|| gridScreenSizeDense > gridDrawThreshold )
{
DrawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ),
VECTOR2D( i * gridSize.x, gridEndY * gridSize.y ) );
}
}
// Restore old values
SetLineWidth( savedLineWidth );
SetStrokeColor( savedColor );
}
This diff is collapsed.
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Graphics Abstraction Layer (GAL) for OpenGL
*
* Shader class
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <iostream>
#include <fstream>
#include <wx/log.h>
#include <gal/opengl/shader.h>
using namespace KiGfx;
SHADER::SHADER()
{
isProgramCreated = false;
isShaderLinked = false;
maximumVertices = 4;
geomInputType = GL_LINES;
geomOutputType = GL_LINES;
}
SHADER::~SHADER()
{
if( isProgramCreated )
{
// Delete the shaders and the program
for( std::deque<GLuint>::iterator it = shaderNumbers.begin(); it != shaderNumbers.end();
it++ )
{
glDeleteShader( *it );
}
glDeleteProgram( programNumber );
}
}
void SHADER::ProgramInfo( GLuint aProgram )
{
GLint glInfoLogLength = 0;
GLint writtenChars = 0;
// Get the length of the info string
glGetProgramiv( aProgram, GL_INFO_LOG_LENGTH, &glInfoLogLength );
// Print the information
if( glInfoLogLength > 2 )
{
GLchar* glInfoLog = new GLchar[glInfoLogLength];
glGetProgramInfoLog( aProgram, glInfoLogLength, &writtenChars, glInfoLog );
wxLogInfo( wxString::FromUTF8( (char*) glInfoLog ) );
delete glInfoLog;
}
}
std::string SHADER::ReadSource( std::string aShaderSourceName )
{
// Open the shader source for reading
std::ifstream inputFile( aShaderSourceName.c_str(), std::ifstream::in );
std::string shaderSource;
if( !inputFile )
{
wxLogError( wxString::FromUTF8( "Can't read the shader source: " ) +
wxString( aShaderSourceName.c_str(), wxConvUTF8 ) );
exit( 1 );
}
std::string shaderSourceLine;
// Read all lines from the text file
while( getline( inputFile, shaderSourceLine ) )
{
shaderSource += shaderSourceLine;
shaderSource += "\n";
}
return shaderSource;
}
void SHADER::AddSource( std::string aShaderSourceName, ShaderType aShaderType )
{
if( isShaderLinked )
{
wxLogError( wxString::FromUTF8( "Shader is already linked!" ) );
}
// Create the program
if( !isProgramCreated )
{
programNumber = glCreateProgram();
isProgramCreated = true;
}
// Load shader sources
std::string shaderSource = ReadSource( aShaderSourceName );
// Create a shader
GLuint shaderNumber = glCreateShader( aShaderType );
shaderNumbers.push_back( shaderNumber );
// Get the program info
ProgramInfo( programNumber );
// Copy to char array
char* source = new char[shaderSource.size() + 1];
strcpy( source, shaderSource.c_str() );
const char** source_ = (const char**) ( &source );
// Attach the source
glShaderSource( shaderNumber, 1, source_, NULL );
ProgramInfo( programNumber );
// Compile and attach shader to the program
glCompileShader( shaderNumber );
glAttachShader( programNumber, shaderNumber );
ProgramInfo( programNumber );
// Special handling for the geometry shader
if( aShaderType == SHADER_TYPE_GEOMETRY )
{
glProgramParameteriEXT( programNumber, GL_GEOMETRY_VERTICES_OUT_EXT, maximumVertices );
glProgramParameteriEXT( programNumber, GL_GEOMETRY_INPUT_TYPE_EXT, geomInputType );
glProgramParameteriEXT( programNumber, GL_GEOMETRY_OUTPUT_TYPE_EXT, geomOutputType );
}
// Delete the allocated char array
delete[] source;
}
void SHADER::ConfigureGeometryShader( GLuint maxVertices, GLuint geometryInputType,
GLuint geometryOutputType )
{
maximumVertices = maxVertices;
geomInputType = geometryInputType;
geomOutputType = geometryOutputType;
}
void SHADER::Link()
{
// Shader linking
glLinkProgram( programNumber );
ProgramInfo( programNumber );
// Check the Link state
GLint linkStatus = 0;
glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB, &linkStatus );
if( !linkStatus )
{
wxLogError( wxString::FromUTF8( "Can't link the shaders!" ) );
exit( 1 );
}
isShaderLinked = true;
}
void SHADER::Use()
{
glUseProgram( programNumber );
}
void SHADER::Deactivate()
{
glUseProgram( 0 );
}
void SHADER::AddParameter( std::string aParameterName )
{
GLint location = glGetUniformLocation( programNumber, aParameterName.c_str() );
if( location != -1 )
{
parameterLocation.push_back( location );
}
}
void SHADER::SetParameter( int parameterNumber, float value )
{
glUniform1f( parameterLocation[parameterNumber], value );
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Fragment shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// This shader requires GLSL 1.2
#version 120
// Input variables
flat varying vec4 center_;
flat varying vec2 radius_;
flat varying vec4 colorA_;
flat varying vec4 colorB_;
void main( void )
{
// Compute the distance from the circle edge
float distA = distance( center_, gl_FragCoord ) - radius_.y;
float distB = radius_.x - distance( center_, gl_FragCoord );
// Limit the range to [ 0 .. 1 ]
if( distA < 0 ) distA = 0;
if( distA > 1 ) distA = 1;
if( distB < 0 ) distB = 0;
if( distB > 1 ) distB = 1;
// Points with a larger distance from the edge are set deeper
gl_FragDepth = gl_FragCoord.z + distA * 0.001 + distB * 0.001;
// Compute the color
vec4 color;
color.r = colorA_.r;
color.g = colorA_.g;
color.b = colorA_.b;
color.a = colorA_.a * ( 1 - distA ) * ( 1 - distB );
// Now output the edge fragment color
gl_FragColor = color;
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Geometry shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// This shader requires GLSL 1.2
#version 120
#extension GL_EXT_geometry_shader4: enable
#extension GL_EXT_gpu_shader4: enable
uniform float viewPortX2;
uniform float viewPortY2;
flat varying vec4 center_;
flat varying vec2 radius_;
flat varying vec4 colorA_;
const float PI = 3.141592654;
const float EPSILON = 0.01;
const float smallestValue = 1.175494351e-38;
const int SEGMENTS = 16;
const float PIXEL_EXTEND = 1.5;
void main()
{
vec4 center = gl_PositionIn[0];
vec4 radius = gl_PositionIn[1];
center_ = gl_ModelViewProjectionMatrix * center;
// Compute the outer and inner radius in screen coordinates
// This could be further optimized
radius_.x = ( gl_ModelViewProjectionMatrix * vec4(radius.x, 0, 0, 1) ).x;
radius_.x = abs( radius_.x - (gl_ModelViewProjectionMatrix * vec4(0, 0, 0, 1) ).x ) * viewPortX2;
radius_.y = ( gl_ModelViewProjectionMatrix * vec4(radius.y, 0, 0, 1) ).x;
radius_.y = abs( radius_.y - (gl_ModelViewProjectionMatrix * vec4(0, 0, 0, 1) ).x ) * viewPortX2;
// Compute the center point in screen coordinates
center_.x = center_.x * viewPortX2 + viewPortX2;
center_.y = center_.y * viewPortY2 + viewPortY2;
// Compute the extend value, first make sure that the outline is inside the triangles and second add
// a margin for one pixel for smooth edges
float extendInner = 1.0;
float extendOuter = 0;
if( radius_.y > smallestValue )
{
extendOuter += PIXEL_EXTEND / radius_.y;
}
extendOuter += 1.0 / cos( PI / SEGMENTS );
colorA_ = gl_FrontColorIn[0];
// Create a quad strip for the outer circle edge
for( float alpha = 0, inc = 2 * PI / SEGMENTS, limit = 2 * PI + EPSILON;
alpha < limit; alpha += inc )
{
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendInner * radius.y * cos( alpha ),
center.y + extendInner * radius.y * sin( alpha ), center.zw );
EmitVertex();
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendOuter * radius.y * cos( alpha ),
center.y + extendOuter * radius.y * sin( alpha ), center.zw );
EmitVertex();
}
EndPrimitive();
if( radius.x > 0 )
{
extendInner = cos( PI / SEGMENTS ) - PIXEL_EXTEND / radius_.x;
if( extendInner < 0.0 )
{
extendInner = 0;
}
extendOuter = 1.0 / cos( PI / SEGMENTS);
// Create a quad strip for the inner circle edge
for( float alpha = 0, inc = 2 * PI / SEGMENTS, limit = 2 * PI + EPSILON;
alpha < limit; alpha += inc )
{
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendOuter * radius.x * cos( alpha ),
center.y + extendOuter * radius.x * sin( alpha ), center.zw );
EmitVertex();
gl_Position = gl_ModelViewProjectionMatrix *
vec4( center.x + extendInner * radius.x * cos( alpha ),
center.y + extendInner * radius.x * sin( alpha ), center.zw );
EmitVertex();
}
EndPrimitive();
}
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Vertex shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// This shader requires GLSL 1.2
#version 120
void main()
{
// Simple pass-through
gl_Position = gl_Vertex;
gl_FrontColor = gl_Color;
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Fragment shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#version 120
#extension GL_EXT_gpu_shader4: enable
varying float dist;
void main()
{
float d = dist;
gl_FragDepth = gl_FragCoord.z + d * 0.001;
gl_FragColor = vec4( gl_Color.rgb, gl_Color.a * ( 1 - d ) );
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Geometry shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#version 120
#extension GL_EXT_geometry_shader4: enable
#extension GL_EXT_gpu_shader4: enable
uniform float viewPortX2;
uniform float viewPortY2;
varying float dist;
void main()
{
// Compute the transformed start and end points
vec2 startPoint = gl_PositionIn[0].xy;
vec2 endPoint = gl_PositionIn[1].xy;
float lineWidth = gl_PositionIn[1].z;
// Compute vector start -> end
vec2 startEndVector = endPoint.xy - startPoint.xy;
float lineLength = distance( startPoint, endPoint );
float scale = 0.0;
if( lineLength > 0.0 )
{
scale = 0.5 * lineWidth / lineLength;
}
else
{
scale = 0.0;
}
// Compute the edge points of the line
vec2 perpendicularVector = scale * vec2( -startEndVector.y, startEndVector.x );
vec2 point1 = startPoint + perpendicularVector;
vec2 point2 = startPoint - perpendicularVector;
vec2 point3 = endPoint + perpendicularVector;
vec2 point4 = endPoint - perpendicularVector;
vec4 point1T = gl_ModelViewProjectionMatrix * vec4( point1, gl_PositionIn[0].zw );
vec4 point2T = gl_ModelViewProjectionMatrix * vec4( point2, gl_PositionIn[0].zw );
vec4 point3T = gl_ModelViewProjectionMatrix * vec4( point3, gl_PositionIn[0].zw );
vec4 point4T = gl_ModelViewProjectionMatrix * vec4( point4, gl_PositionIn[0].zw );
// Construct the quad for the middle
gl_FrontColor = gl_FrontColorIn[0];
dist = 0;
gl_Position = point1T;
EmitVertex();
dist = 0;
gl_Position = point2T;
EmitVertex();
dist = 0;
gl_Position = point3T;
EmitVertex();
dist = 0;
gl_Position = point4T;
EmitVertex();
EndPrimitive();
// Compute the perpendicular vector with 1 pixel width
vec2 v = point1T.xy - point3T.xy;
vec4 onePix = 0.5 * vec4( -v.y, v.x, 0, 0 );
onePix *= 1.0 / sqrt( dot( onePix, onePix ) );
onePix.x *= 1.0 / viewPortX2;
onePix.y *= 1.0 / viewPortY2;
gl_FrontColor = gl_FrontColorIn[0];
dist = 1;
gl_Position = point1T + onePix;
EmitVertex();
dist = 1;
gl_Position = point3T + onePix;
EmitVertex();
dist = 0;
gl_Position = point1T;
EmitVertex();
dist = 0;
gl_Position = point3T;
EmitVertex();
EndPrimitive();
dist = 1;
gl_Position = point2T - onePix;
EmitVertex();
dist = 1;
gl_Position = point4T - onePix;
EmitVertex();
dist = 0;
gl_Position = point2T;
EmitVertex();
dist = 0;
gl_Position = point4T;
EmitVertex();
EndPrimitive();
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Vertex shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// This shader requires GLSL 1.2
#version 120
void main()
{
// Simple pass-through
gl_Position = gl_Vertex;
gl_FrontColor = gl_Color;
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Fragment shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#version 120
varying float aspect;
void main()
{
vec2 v = abs( gl_TexCoord[0].xy - vec2( 0.5, 0.5 ) ) * 2.0 - vec2( aspect, 0.0 );
vec2 d = vec2( v.x / ( 1.0 - aspect ), v.y );
if( v.x <= 0.0 || (dot( d, d ) < 1.0 ) )
gl_FragColor = gl_Color;
else
discard;
// gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Vertex shader
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#version 120
varying float aspect;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
aspect = gl_Normal.x;
}
/*
* 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 Kicad Developers, see change_log.txt for contributors.
*
* Stroke font class
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <gal/stroke_font.h>
#include <gal/graphics_abstraction_layer.h>
using namespace KiGfx;
STROKE_FONT::STROKE_FONT( GAL* aGal ) :
m_gal( aGal ),
m_bold( false ),
m_italic( false ),
m_mirrored( false )
{
// Default values
m_scaleFactor = 1.0 / 21.0;
m_glyphSize = VECTOR2D( 10.0, 10.0 );
m_verticalJustify = GR_TEXT_VJUSTIFY_BOTTOM;
m_horizontalJustify = GR_TEXT_HJUSTIFY_LEFT;
}
STROKE_FONT::~STROKE_FONT()
{
}
bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNewStrokeFontSize )
{
m_glyphs.clear();
m_glyphBoundingBoxes.clear();
for( int j = 0; j < aNewStrokeFontSize; j++ )
{
Glyph glyph;
double glyphStartX;
double glyphEndX;
VECTOR2D glyphBoundingX;
std::deque<VECTOR2D> pointList;
int i = 0;
while( aNewStrokeFont[j][i] )
{
VECTOR2D point;
char coordinate[2];
for( int k = 0; k < 2; k++ )
{
coordinate[k] = aNewStrokeFont[j][i + k];
}
if( i < 2 )
{
// The first two values contain the width of the char
glyphStartX = coordinate[0] - 'R';
glyphEndX = coordinate[1] - 'R';
glyphBoundingX = VECTOR2D( 0, glyphEndX - glyphStartX );
}
else if( ( coordinate[0] == ' ' ) && ( coordinate[1] == 'R' ) )
{
// Raise pen
if( pointList.size() > 0 )
glyph.push_back( pointList );
pointList.clear();
}
else
{
// Every coordinate description of the Hershey format has an offset,
// it has to be subtracted
point.x = (double) ( coordinate[0] - 'R' ) - glyphStartX;
point.y = (double) ( coordinate[1] - 'R' ) - 11.0;
pointList.push_back( point );
}
i += 2;
}
if( pointList.size() > 0 )
glyph.push_back( pointList );
m_glyphs.push_back( glyph );
// Compute the bounding box of the glyph
m_glyphBoundingBoxes.push_back( computeBoundingBox( glyph, glyphBoundingX ) );
}
return true;
}
void STROKE_FONT::LoadAttributes( const EDA_TEXT* aText )
{
SetGlyphSize( VECTOR2D( aText->GetSize() ) );
SetHorizontalJustify( aText->GetHorizJustify() );
SetVerticalJustify( aText->GetVertJustify() );
SetBold( aText->IsBold() );
SetItalic( aText->IsItalic() );
SetMirrored( aText->IsMirrored() );
}
BOX2D STROKE_FONT::computeBoundingBox( Glyph aGlyph, VECTOR2D aGlyphBoundingX )
{
BOX2D boundingBox;
std::deque<VECTOR2D> boundingPoints;
boundingPoints.push_back( VECTOR2D( aGlyphBoundingX.x, 0 ) );
boundingPoints.push_back( VECTOR2D( aGlyphBoundingX.y, 0 ) );
for( Glyph::iterator pointListIt = aGlyph.begin(); pointListIt != aGlyph.end(); ++pointListIt )
{
for( std::deque<VECTOR2D>::iterator pointIt = pointListIt->begin();
pointIt != pointListIt->end(); ++pointIt )
{
boundingPoints.push_back( VECTOR2D( aGlyphBoundingX.x, pointIt->y ) );
}
}
boundingBox.Compute( boundingPoints );
return boundingBox;
}
void STROKE_FONT::Draw( std::string aText, VECTOR2D aPosition, double aRotationAngle )
{
// Compute the text size
VECTOR2D textsize = computeTextSize( aText );
// Context needs to be saved before any transformations
m_gal->Save();
m_gal->Translate( aPosition );
m_gal->Rotate( -aRotationAngle );
// Adjust the text position to the given alignment
switch( m_horizontalJustify )
{
case GR_TEXT_HJUSTIFY_CENTER:
m_gal->Translate( VECTOR2D( -textsize.x / 2, 0 ) );
break;
case GR_TEXT_HJUSTIFY_RIGHT:
m_gal->Translate( VECTOR2D( -textsize.x, 0 ) );
break;
case GR_TEXT_HJUSTIFY_LEFT:
break;
default:
break;
}
switch( m_verticalJustify )
{
case GR_TEXT_VJUSTIFY_CENTER:
m_gal->Translate( VECTOR2D( 0, textsize.y / 2 ) );
break;
case GR_TEXT_VJUSTIFY_TOP:
m_gal->Translate( VECTOR2D( 0, textsize.y ) );
break;
case GR_TEXT_VJUSTIFY_BOTTOM:
break;
default:
break;
}
double xOffset, glyphSizeX;
if( m_mirrored )
{
// In case of mirrored text invert the X scale of points and their X direction
// (m_glyphSize.x) and start drawing from the position where text normally should end
// (textsize.x)
xOffset = textsize.x;
glyphSizeX = -m_glyphSize.x;
}
else
{
xOffset = 0.0;
glyphSizeX = m_glyphSize.x;
}
double scaleY = m_scaleFactor * m_glyphSize.y;
double scaleX = m_scaleFactor * glyphSizeX;
if( m_bold )
{
m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 );
}
for( std::string::iterator chIt = aText.begin(); chIt != aText.end(); chIt++ )
{
GlyphList::iterator glyphIt = m_glyphs.begin();
std::deque<BOX2D>::iterator bbIt = m_glyphBoundingBoxes.begin();
advance( glyphIt, (int) ( *chIt ) - (int) ' ' );
advance( bbIt, (int) ( *chIt ) - (int) ' ' );
Glyph glyph = *glyphIt;
for( Glyph::iterator pointListIt = glyph.begin(); pointListIt != glyph.end();
pointListIt++ )
{
std::deque<VECTOR2D> pointListScaled;
for( std::deque<VECTOR2D>::iterator pointIt = pointListIt->begin();
pointIt != pointListIt->end(); pointIt++ )
{
VECTOR2D pointPos( pointIt->x * scaleX + xOffset, pointIt->y * scaleY );
if( m_italic )
{
// FIXME should be done other way - referring to the lowest Y value of point
// because now italic fonts are translated a bit
pointPos.x += pointPos.y * 0.1;
}
pointListScaled.push_back( pointPos );
}
m_gal->DrawPolyline( pointListScaled );
}
xOffset += m_scaleFactor * glyphSizeX *
( bbIt->GetEnd().x - bbIt->GetOrigin().x );
}
m_gal->Restore();
}
VECTOR2D STROKE_FONT::computeTextSize( std::string aText )
{
VECTOR2D result = VECTOR2D( 0.0, 0.0 );
for( std::string::iterator chIt = aText.begin(); chIt != aText.end(); chIt++ )
{
std::deque<BOX2D>::iterator bbIt = m_glyphBoundingBoxes.begin();
advance( bbIt, (int) ( *chIt ) - (int) ' ' );
result.x += m_scaleFactor * m_glyphSize.x * ( bbIt->GetEnd().x - bbIt->GetOrigin().x );
}
result.y = m_glyphSize.y;
return result;
}
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <eda_text.h>
#include <view/view.h>
#include <painter.h>
#include <gal/stroke_font.h>
#include <newstroke_font.h>
using namespace KiGfx;
RENDER_SETTINGS::RENDER_SETTINGS()
{
// Set the default initial values
m_selectionBorderColor = COLOR4D( 1.0, 1.0, 1.0, 1.0 );
m_netLabelColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
m_highlightFactor = 0.5;
m_selectFactor = 0.5;
m_layerOpacity = 0.8;
m_highlightEnabled = false;
m_hiContrastEnabled = false;
m_hiContrastFactor = 0.2;
// Store the predefined colors used in KiCad in format used by GAL
for( int i = 0; i < NBCOLOR; i++ )
{
m_legacyColorMap[ColorRefs[i].m_Numcolor] = COLOR4D( (double) ColorRefs[i].m_Red / 255.0,
(double) ColorRefs[i].m_Green / 255.0,
(double) ColorRefs[i].m_Blue / 255.0,
m_layerOpacity );
}
}
RENDER_SETTINGS::~RENDER_SETTINGS()
{
}
void RENDER_SETTINGS::Update()
{
m_hiContrastColor = COLOR4D( m_hiContrastFactor, m_hiContrastFactor, m_highlightFactor,
m_layerOpacity );
}
PAINTER::PAINTER( GAL* aGal ) :
m_gal( aGal ), m_settings( NULL )
{
m_stroke_font = new STROKE_FONT( aGal );
m_stroke_font->LoadNewStrokeFont( newstroke_font, newstroke_font_bufsize );
}
PAINTER::~PAINTER()
{
delete m_stroke_font;
}
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file profile.h:
* @brief Simple profiling functions for measuring code execution time. Currently only Linux is
* supported.
*/
#ifndef __PROFILE_H
#define __PROFILE_H
#ifdef __linux__
#include <sys/time.h>
#endif
#include <stdint.h>
/**
* Function rdtsc
* Returns processor's time-stamp counter. Main purpose is precise time measuring of code
* execution time.
* @return unsigned long long - Value of time-stamp counter.
*/
#if defined(__i386__)
static __inline__ unsigned long long rdtsc()
{
unsigned long long int x;
__asm__ volatile ( ".byte 0x0f, 0x31" : "=A" ( x ) );
return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc()
{
unsigned hi, lo;
__asm__ __volatile__ ( "rdtsc" : "=a" ( lo ), "=d" ( hi ) );
return ( (unsigned long long) lo ) | ( ( (unsigned long long) hi ) << 32 );
}
#elif defined(__powerpc__)
static __inline__ unsigned long long rdtsc()
{
unsigned long long int result = 0;
unsigned long int upper, lower, tmp;
__asm__ volatile (
"0: \n"
"\tmftbu %0 \n"
"\tmftb %1 \n"
"\tmftbu %2 \n"
"\tcmpw %2,%0 \n"
"\tbne 0b \n"
: "=r" ( upper ), "=r" ( lower ), "=r" ( tmp )
);
result = upper;
result = result << 32;
result = result | lower;
return result;
}
#endif /* __powerpc__ */
// Fixme: OS X version
/**
* Function get_tics
* Returns the number of milliseconds that have elapsed since the system was started.
* @return uint64_t Number of milliseconds.
*/
static inline uint64_t get_tics()
{
#if defined(__linux__)
struct timezone tz = { 0, 0 };
struct timeval tv;
gettimeofday( &tv, &tz );
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
#elif defined _WIN32 || defined _WIN64
// TODO to be tested
return GetTickCount();
#else
return 0;
#endif
}
/**
* Structure for storing data related to profiling counters.
*/
struct prof_counter
{
uint64_t value; /// Stored timer value
bool use_rdtsc; /// Method of time measuring (rdtsc or tics)
};
/**
* Function prof_start
* Begins code execution time counting for a given profiling counter.
* @param cnt is the counter which should be started.
* @param use_rdtsc tells if processor's time-stamp counter should be used for time counting.
* Otherwise is system tics method will be used.
*/
static inline void prof_start( prof_counter* cnt, bool use_rdtsc )
{
cnt->use_rdtsc = use_rdtsc;
if( use_rdtsc )
{
cnt->value = rdtsc();
}
else
{
cnt->value = get_tics();
}
}
/**
* Function prof_stop
* Ends code execution time counting for a given profiling counter.
* @param cnt is the counter which should be stopped.
*/
static inline void prof_end( prof_counter* cnt )
{
if( cnt->use_rdtsc )
cnt->value = rdtsc() - cnt->value;
else
cnt->value = get_tics() - cnt->value;
}
#endif
This diff is collapsed.
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <gal/definitions.h>
#include <view/view_item.h>
#include <view/view.h>
using namespace KiGfx;
void VIEW_ITEM::ViewSetVisible( bool aIsVisible )
{
bool update = false;
if( m_viewVisible != aIsVisible )
{
update = true;
}
m_viewVisible = aIsVisible;
// update only if the visibility has really changed
if( update )
{
ViewUpdate( APPEARANCE );
}
}
void VIEW_ITEM::ViewUpdate( int aUpdateFlags, bool aForceImmediateRedraw )
{
m_view->invalidateItem( this, aUpdateFlags );
if( aForceImmediateRedraw )
{
m_view->Redraw();
}
}
void VIEW_ITEM::ViewRelease()
{
if( m_view && m_view->IsDynamic() )
{
m_view->Remove( this );
}
}
/*
* 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) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/wx.h>
#include <wx/window.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
using namespace KiGfx;
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
VIEW_CONTROLS( aView ),
m_autoPanMargin( 0.1 ),
m_autoPanSpeed( 0.15 ),
m_autoPanCornerRatio( 0.1 ),
m_parentPanel( aParentPanel )
{
m_parentPanel->Connect( wxEVT_MOTION, wxMouseEventHandler(
WX_VIEW_CONTROLS::onMotion ), NULL, this );
m_parentPanel->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler(
WX_VIEW_CONTROLS::onWheel ), NULL, this );
m_parentPanel->Connect( wxEVT_RIGHT_UP, wxMouseEventHandler(
WX_VIEW_CONTROLS::onButton ), NULL, this );
m_parentPanel->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler(
WX_VIEW_CONTROLS::onButton ), NULL, this );
}
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& event )
{
VECTOR2D mousePoint( event.GetX(), event.GetY() );
if( event.Dragging() )
{
if( m_isDragPanning )
{
VECTOR2D d = m_dragStartPoint - mousePoint;
VECTOR2D delta = m_view->ToWorld( d, false );
m_view->SetCenter( m_lookStartPoint + delta );
m_parentPanel->Refresh();
}
else
{
event.Skip();
}
}
}
void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& event )
{
const double wheelPanSpeed = 0.001;
if( event.ControlDown() )
{
wxLongLong timeStamp = wxGetLocalTimeMillis();
double timeDiff = timeStamp.ToDouble() - m_timeStamp.ToDouble();
m_timeStamp = timeStamp;
double zoomScale;
// Set scaling speed depending on scroll wheel event interval
if( timeDiff < 500 && timeDiff > 0 )
{
zoomScale = ( event.GetWheelRotation() > 0.0 ) ? 2.05 - timeDiff / 500 :
1.0 / ( 2.05 - timeDiff / 500 );
}
else
{
zoomScale = ( event.GetWheelRotation() > 0.0 ) ? 1.05 : 0.95;
}
VECTOR2D anchor = m_view->ToWorld( VECTOR2D( event.GetX(), event.GetY() ) );
m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
m_parentPanel->Refresh();
}
else
{
VECTOR2D scrollVec = m_view->ToWorld( m_view->GetScreenPixelSize() *
( (double) event.GetWheelRotation() * wheelPanSpeed ), false );
double scrollSpeed;
if( abs( scrollVec.x ) > abs( scrollVec.y ) )
scrollSpeed = scrollVec.x;
else
scrollSpeed = scrollVec.y;
VECTOR2D t = m_view->GetScreenPixelSize();
VECTOR2D delta( event.ShiftDown() ? scrollSpeed : 0.0,
!event.ShiftDown() ? scrollSpeed : 0.0 );
m_view->SetCenter( m_view->GetCenter() + delta );
m_parentPanel->Refresh();
}
}
void WX_VIEW_CONTROLS::onButton( wxMouseEvent& event )
{
if( event.RightDown() )
{
m_isDragPanning = true;
m_dragStartPoint = VECTOR2D( event.GetX(), event.GetY() );
m_lookStartPoint = m_view->GetCenter(); // ookAtPoint();
}
else if( event.RightUp() )
{
m_isDragPanning = false;
}
event.Skip();
}
This diff is collapsed.
...@@ -104,6 +104,13 @@ target_link_libraries(cvpcb ...@@ -104,6 +104,13 @@ target_link_libraries(cvpcb
${GDI_PLUS_LIBRARIES} ${GDI_PLUS_LIBRARIES}
) )
if(KICAD_GAL)
target_link_libraries(cvpcb
gal
${GLEW_LIBRARIES}
)
endif(KICAD_GAL)
### ###
# Add cvpcb as install target # Add cvpcb as install target
### ###
......
This diff is collapsed.
...@@ -248,6 +248,9 @@ public: ...@@ -248,6 +248,9 @@ public:
static std::string FormatInternalUnits( const wxPoint& aPoint ); static std::string FormatInternalUnits( const wxPoint& aPoint );
static std::string FormatInternalUnits( const wxSize& aSize ); static std::string FormatInternalUnits( const wxSize& aSize );
/// @copydoc VIEW_ITEM::ViewGetLayers()
virtual void ViewGetLayers( int aLayers[], int& aCount ) const;
}; };
#endif /* BOARD_ITEM_STRUCT_H */ #endif /* BOARD_ITEM_STRUCT_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment