merge in a year's worth of CERN work
This commit is contained in:
commit
3e18a46758
|
@ -414,6 +414,6 @@ void CALLBACK tessErrorCB( GLenum errorCode )
|
||||||
errorStr = gluErrorString( errorCode );
|
errorStr = gluErrorString( errorCode );
|
||||||
|
|
||||||
// DEBUG //
|
// DEBUG //
|
||||||
D( printf( "Tess ERROR: %s\n", errorStr ); )
|
DBG( printf( "Tess ERROR: %s\n", errorStr ); )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ int VRML_MODEL_PARSER::readMaterial( FILE* file, int* LineNum )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D( printf( "ReadMaterial error: material not found\n" ) );
|
DBG( printf( "ReadMaterial error: material not found\n" ) );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ int VRML_MODEL_PARSER::readChildren( FILE* file, int* LineNum )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "ReadChildren error line %d <%s> \n", *LineNum, text ) );
|
DBG( printf( "ReadChildren error line %d <%s> \n", *LineNum, text ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ int VRML_MODEL_PARSER::readShape( FILE* file, int* LineNum )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "ReadShape error line %d <%s> \n", *LineNum, text ) );
|
DBG( printf( "ReadShape error line %d <%s> \n", *LineNum, text ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ int VRML_MODEL_PARSER::readAppearance( FILE* file, int* LineNum )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "ReadAppearance error line %d <%s> \n", *LineNum, text ) );
|
DBG( printf( "ReadAppearance error line %d <%s> \n", *LineNum, text ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,19 +197,19 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
||||||
if( !parseDoubleTriplet( properties[ wxT( "diffuseColor" ) ],
|
if( !parseDoubleTriplet( properties[ wxT( "diffuseColor" ) ],
|
||||||
material->m_DiffuseColor ) )
|
material->m_DiffuseColor ) )
|
||||||
{
|
{
|
||||||
D( printf("diffuseColor parsing error") );
|
DBG( printf("diffuseColor parsing error") );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !parseDoubleTriplet( properties[ wxT( "specularColor" ) ],
|
if( !parseDoubleTriplet( properties[ wxT( "specularColor" ) ],
|
||||||
material->m_SpecularColor ) )
|
material->m_SpecularColor ) )
|
||||||
{
|
{
|
||||||
D( printf("specularColor parsing error") );
|
DBG( printf("specularColor parsing error") );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !parseDoubleTriplet( properties[ wxT( "emissiveColor" ) ],
|
if( !parseDoubleTriplet( properties[ wxT( "emissiveColor" ) ],
|
||||||
material->m_EmissiveColor ) )
|
material->m_EmissiveColor ) )
|
||||||
{
|
{
|
||||||
D( printf("emissiveColor parsing error") );
|
DBG( printf("emissiveColor parsing error") );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxStringTokenizer values;
|
wxStringTokenizer values;
|
||||||
|
@ -221,7 +221,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "ambienterror" ) );
|
DBG( printf( "ambienterror" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
values.SetString( properties[ wxT( "shininess" ) ] );
|
values.SetString( properties[ wxT( "shininess" ) ] );
|
||||||
|
@ -232,7 +232,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "shininess error" ) );
|
DBG( printf( "shininess error" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
values.SetString( properties[ wxT( "transparency" ) ] );
|
values.SetString( properties[ wxT( "transparency" ) ] );
|
||||||
|
@ -243,7 +243,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "trans error") );
|
DBG( printf( "trans error") );
|
||||||
}
|
}
|
||||||
|
|
||||||
material->SetMaterial();
|
material->SetMaterial();
|
||||||
|
@ -303,7 +303,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D( printf( "ReadMaterial error: material not found\n" ) );
|
DBG( printf( "ReadMaterial error: material not found\n" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode,
|
||||||
tokens.GetNextToken().ToDouble( &rotation.z ) &&
|
tokens.GetNextToken().ToDouble( &rotation.z ) &&
|
||||||
tokens.GetNextToken().ToDouble( &angle ) ) )
|
tokens.GetNextToken().ToDouble( &angle ) ) )
|
||||||
{
|
{
|
||||||
D( printf("rotation read error") );
|
DBG( printf("rotation read error") );
|
||||||
}
|
}
|
||||||
|
|
||||||
double vrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits *
|
double vrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits *
|
||||||
|
@ -407,7 +407,7 @@ void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode,
|
||||||
|
|
||||||
if( points.size() % 3 != 0 )
|
if( points.size() % 3 != 0 )
|
||||||
{
|
{
|
||||||
D( printf( "Number of points is incorrect" ) );
|
DBG( printf( "Number of points is incorrect" ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ option( KICAD_SCRIPTING_MODULES
|
||||||
option( KICAD_SCRIPTING_WXPYTHON
|
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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 )
|
||||||
|
@ -230,12 +230,27 @@ include( ExternalProject )
|
||||||
#================================================
|
#================================================
|
||||||
include( CheckFindPackageResult )
|
include( CheckFindPackageResult )
|
||||||
|
|
||||||
|
# Turn on wxWidgets compatibility mode for some classes
|
||||||
|
add_definitions(-DWX_COMPATIBILITY)
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# Find OpenGL library #
|
# Find OpenGL library #
|
||||||
#######################
|
#######################
|
||||||
find_package( OpenGL QUIET )
|
find_package( OpenGL QUIET )
|
||||||
check_find_package_result( OPENGL_FOUND "OpenGL" )
|
check_find_package_result( OPENGL_FOUND "OpenGL" )
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# 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")
|
||||||
|
|
||||||
# Download boost and possibly build parts of it
|
# Download boost and possibly build parts of it
|
||||||
#################################################
|
#################################################
|
||||||
include( download_boost )
|
include( download_boost )
|
||||||
|
@ -360,6 +375,7 @@ add_subdirectory( cvpcb )
|
||||||
add_subdirectory( eeschema )
|
add_subdirectory( eeschema )
|
||||||
add_subdirectory( gerbview )
|
add_subdirectory( gerbview )
|
||||||
add_subdirectory( kicad )
|
add_subdirectory( kicad )
|
||||||
|
add_subdirectory( lib_dxf )
|
||||||
add_subdirectory( pcbnew )
|
add_subdirectory( pcbnew )
|
||||||
add_subdirectory( polygon )
|
add_subdirectory( polygon )
|
||||||
add_subdirectory( pagelayout_editor )
|
add_subdirectory( pagelayout_editor )
|
||||||
|
@ -375,12 +391,14 @@ add_subdirectory( tools )
|
||||||
add_dependencies( pcbnew boost )
|
add_dependencies( pcbnew boost )
|
||||||
add_dependencies( eeschema boost )
|
add_dependencies( eeschema boost )
|
||||||
add_dependencies( cvpcb boost )
|
add_dependencies( cvpcb boost )
|
||||||
|
add_dependencies( gal boost )
|
||||||
add_dependencies( common boost )
|
add_dependencies( common boost )
|
||||||
add_dependencies( pcbcommon boost )
|
add_dependencies( pcbcommon boost )
|
||||||
add_dependencies( 3d-viewer boost )
|
add_dependencies( 3d-viewer boost )
|
||||||
add_dependencies( pcad2kicadpcb boost )
|
add_dependencies( pcad2kicadpcb boost )
|
||||||
add_dependencies( polygon boost )
|
add_dependencies( polygon boost )
|
||||||
add_dependencies( pl_editor boost )
|
add_dependencies( pl_editor boost )
|
||||||
|
add_dependencies( pnsrouter boost )
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
# - Try to find the CAIRO library
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# CAIRO_ROOT_DIR - Set this variable to the root installation of CAIRO
|
||||||
|
#
|
||||||
|
# Read-Only variables:
|
||||||
|
# CAIRO_FOUND - system has the CAIRO library
|
||||||
|
# CAIRO_INCLUDE_DIR - the CAIRO include directory
|
||||||
|
# CAIRO_LIBRARIES - The libraries needed to use CAIRO
|
||||||
|
# CAIRO_VERSION - This is set to $major.$minor.$revision (eg. 0.9.8)
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2012 Dmitry Baryshnikov <polimax at mail dot ru>
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if (PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(_CAIRO cairo)
|
||||||
|
endif (PKG_CONFIG_FOUND)
|
||||||
|
endif (UNIX)
|
||||||
|
|
||||||
|
SET(_CAIRO_ROOT_HINTS
|
||||||
|
$ENV{CAIRO}
|
||||||
|
${CAIRO_ROOT_DIR}
|
||||||
|
)
|
||||||
|
SET(_CAIRO_ROOT_PATHS
|
||||||
|
$ENV{CAIRO}/src
|
||||||
|
/usr
|
||||||
|
/usr/local
|
||||||
|
)
|
||||||
|
SET(_CAIRO_ROOT_HINTS_AND_PATHS
|
||||||
|
HINTS ${_CAIRO_ROOT_HINTS}
|
||||||
|
PATHS ${_CAIRO_ROOT_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(CAIRO_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
cairo.h
|
||||||
|
HINTS
|
||||||
|
${_CAIRO_INCLUDEDIR}
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
"include/cairo"
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(WIN32 AND NOT CYGWIN)
|
||||||
|
# MINGW should go here too
|
||||||
|
IF(MSVC)
|
||||||
|
# Implementation details:
|
||||||
|
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||||
|
FIND_LIBRARY(CAIRO_DEBUG
|
||||||
|
NAMES
|
||||||
|
cairod
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib"
|
||||||
|
"VC"
|
||||||
|
"lib/VC"
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(CAIRO_RELEASE
|
||||||
|
NAMES
|
||||||
|
cairo
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib"
|
||||||
|
"VC"
|
||||||
|
"lib/VC"
|
||||||
|
)
|
||||||
|
|
||||||
|
if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
||||||
|
if(NOT CAIRO_DEBUG)
|
||||||
|
set(CAIRO_DEBUG ${CAIRO_RELEASE})
|
||||||
|
endif(NOT CAIRO_DEBUG)
|
||||||
|
set( CAIRO_LIBRARIES
|
||||||
|
optimized ${CAIRO_RELEASE} debug ${CAIRO_DEBUG}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set( CAIRO_LIBRARIES ${CAIRO_RELEASE})
|
||||||
|
endif()
|
||||||
|
MARK_AS_ADVANCED(CAIRO_DEBUG CAIRO_RELEASE)
|
||||||
|
ELSEIF(MINGW)
|
||||||
|
# same player, for MingW
|
||||||
|
FIND_LIBRARY(CAIRO
|
||||||
|
NAMES
|
||||||
|
cairo
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib"
|
||||||
|
"lib/MinGW"
|
||||||
|
)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(CAIRO)
|
||||||
|
set( CAIRO_LIBRARIES ${CAIRO})
|
||||||
|
ELSE(MSVC)
|
||||||
|
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||||
|
FIND_LIBRARY(CAIRO
|
||||||
|
NAMES
|
||||||
|
cairo
|
||||||
|
HINTS
|
||||||
|
${_CAIRO_LIBDIR}
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib
|
||||||
|
)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(CAIRO)
|
||||||
|
set( CAIRO_LIBRARIES ${CAIRO} )
|
||||||
|
ENDIF(MSVC)
|
||||||
|
ELSE(WIN32 AND NOT CYGWIN)
|
||||||
|
|
||||||
|
FIND_LIBRARY(CAIRO_LIBRARY
|
||||||
|
NAMES
|
||||||
|
cairo
|
||||||
|
HINTS
|
||||||
|
${_CAIRO_LIBDIR}
|
||||||
|
${_CAIRO_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib"
|
||||||
|
"local/lib"
|
||||||
|
)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(CAIRO_LIBRARY)
|
||||||
|
|
||||||
|
# compat defines
|
||||||
|
SET(CAIRO_LIBRARIES ${CAIRO_LIBRARY})
|
||||||
|
|
||||||
|
ENDIF(WIN32 AND NOT CYGWIN)
|
||||||
|
|
||||||
|
# if (CAIRO_INCLUDE_DIR)
|
||||||
|
# file(READ "${CAIRO_INCLUDE_DIR}/gcore/gdal_version.h" _wxgisgdal_VERSION_H_CONTENTS)
|
||||||
|
# string(REGEX REPLACE ".*# define[ \t]+GDAL_RELEASE_NAME[ \t]+\"([0-9A-Za-z.]+)\".*"
|
||||||
|
# "\\1" CAIRO_VERSION ${_wxgisgdal_VERSION_H_CONTENTS})
|
||||||
|
# set(CAIRO_VERSION ${CAIRO_VERSION} CACHE INTERNAL "The version number for wxgisgdal libraries")
|
||||||
|
# endif (CAIRO_INCLUDE_DIR)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
# if (CAIRO_VERSION)
|
||||||
|
# find_package_handle_standard_args(CAIRO
|
||||||
|
# REQUIRED_VARS
|
||||||
|
# CAIRO_LIBRARIES
|
||||||
|
# CAIRO_INCLUDE_DIR
|
||||||
|
# VERSION_VAR
|
||||||
|
# CAIRO_VERSION
|
||||||
|
# FAIL_MESSAGE
|
||||||
|
# "Could NOT find CAIRO, try to set the path to CAIRO root folder in the system variable CAIRO_ROOT_DIR"
|
||||||
|
# )
|
||||||
|
# else (CAIRO_VERSION)
|
||||||
|
find_package_handle_standard_args(CAIRO "Could NOT find CAIRO, try to set the path to CAIRO root folder in the system variable CAIRO"
|
||||||
|
CAIRO_LIBRARIES
|
||||||
|
CAIRO_INCLUDE_DIR
|
||||||
|
)
|
||||||
|
# endif (CAIRO_VERSION)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(CAIRO_INCLUDE_DIR CAIRO_LIBRARIES)
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Copyright (c) 2009 Boudewijn Rempt <boud@valdyas.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
#
|
||||||
|
# - try to find glew library and include files
|
||||||
|
# GLEW_INCLUDE_DIR, where to find GL/glew.h, etc.
|
||||||
|
# GLEW_LIBRARIES, the libraries to link against
|
||||||
|
# GLEW_FOUND, If false, do not try to use GLEW.
|
||||||
|
# Also defined, but not for general use are:
|
||||||
|
# GLEW_GLEW_LIBRARY = the full path to the glew library.
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
|
||||||
|
IF(CYGWIN)
|
||||||
|
|
||||||
|
FIND_PATH( GLEW_INCLUDE_DIR GL/glew.h)
|
||||||
|
|
||||||
|
FIND_LIBRARY( GLEW_GLEW_LIBRARY glew32
|
||||||
|
${OPENGL_LIBRARY_DIR}
|
||||||
|
/usr/lib/w32api
|
||||||
|
/usr/X11R6/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
ELSE(CYGWIN)
|
||||||
|
|
||||||
|
FIND_PATH( GLEW_INCLUDE_DIR GL/glew.h
|
||||||
|
$ENV{GLEW_ROOT_PATH}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY( GLEW_GLEW_LIBRARY
|
||||||
|
NAMES glew glew32 glew32s
|
||||||
|
PATHS
|
||||||
|
$ENV{GLEW_ROOT_PATH}/lib
|
||||||
|
${OPENGL_LIBRARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDIF(CYGWIN)
|
||||||
|
|
||||||
|
ELSE (WIN32)
|
||||||
|
|
||||||
|
IF (APPLE)
|
||||||
|
# These values for Apple could probably do with improvement.
|
||||||
|
FIND_PATH( GLEW_INCLUDE_DIR GL/glew.h
|
||||||
|
/System/Library/Frameworks/GLEW.framework/Versions/A/Headers
|
||||||
|
/opt/local/include
|
||||||
|
${OPENGL_LIBRARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY( GLEW_GLEW_LIBRARY GLEW
|
||||||
|
/opt/local/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
ELSE (APPLE)
|
||||||
|
|
||||||
|
FIND_PATH( GLEW_INCLUDE_DIR GL/glew.h
|
||||||
|
/usr/include/GL
|
||||||
|
/usr/openwin/share/include
|
||||||
|
/usr/openwin/include
|
||||||
|
/usr/X11R6/include
|
||||||
|
/usr/include/X11
|
||||||
|
/opt/graphics/OpenGL/include
|
||||||
|
/opt/graphics/OpenGL/contrib/libglew
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY( GLEW_GLEW_LIBRARY GLEW
|
||||||
|
/usr/openwin/lib
|
||||||
|
/usr/X11R6/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDIF (APPLE)
|
||||||
|
|
||||||
|
ENDIF (WIN32)
|
||||||
|
|
||||||
|
SET( GLEW_FOUND "NO" )
|
||||||
|
IF(GLEW_INCLUDE_DIR)
|
||||||
|
IF(GLEW_GLEW_LIBRARY)
|
||||||
|
# Is -lXi and -lXmu required on all platforms that have it?
|
||||||
|
# If not, we need some way to figure out what platform we are on.
|
||||||
|
SET( GLEW_LIBRARIES
|
||||||
|
${GLEW_GLEW_LIBRARY}
|
||||||
|
${GLEW_cocoa_LIBRARY}
|
||||||
|
)
|
||||||
|
SET( GLEW_FOUND "YES" )
|
||||||
|
|
||||||
|
#The following deprecated settings are for backwards compatibility with CMake1.4
|
||||||
|
SET (GLEW_LIBRARY ${GLEW_LIBRARIES})
|
||||||
|
SET (GLEW_INCLUDE_PATH ${GLEW_INCLUDE_DIR})
|
||||||
|
|
||||||
|
ENDIF(GLEW_GLEW_LIBRARY)
|
||||||
|
ENDIF(GLEW_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF(GLEW_FOUND)
|
||||||
|
IF(NOT GLEW_FIND_QUIETLY)
|
||||||
|
MESSAGE(STATUS "Found Glew: ${GLEW_LIBRARIES}")
|
||||||
|
ENDIF(NOT GLEW_FIND_QUIETLY)
|
||||||
|
ELSE(GLEW_FOUND)
|
||||||
|
IF(GLEW_FIND_REQUIRED)
|
||||||
|
MESSAGE(FATAL_ERROR "Could not find Glew")
|
||||||
|
ENDIF(GLEW_FIND_REQUIRED)
|
||||||
|
ENDIF(GLEW_FOUND)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
GLEW_INCLUDE_DIR
|
||||||
|
GLEW_GLEW_LIBRARY
|
||||||
|
GLEW_Xmu_LIBRARY
|
||||||
|
GLEW_Xi_LIBRARY
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
# CMake script file to process a GLSL source file, so it can be included
|
||||||
|
# in C array and compiled in to an application.
|
||||||
|
|
||||||
|
# number of input files
|
||||||
|
list( LENGTH inputFiles shadersNumber )
|
||||||
|
|
||||||
|
# check if GLSL source files were updated since the last time
|
||||||
|
set( update "FALSE" )
|
||||||
|
foreach( inputFile ${inputFiles} )
|
||||||
|
if( ${inputFile} IS_NEWER_THAN ${outputFile} )
|
||||||
|
set( update "TRUE" )
|
||||||
|
endif( ${inputFile} IS_NEWER_THAN ${outputFile} )
|
||||||
|
endforeach( inputFile ${inputFiles} )
|
||||||
|
|
||||||
|
if( NOT update )
|
||||||
|
message( "Headers are up-to-date" )
|
||||||
|
return()
|
||||||
|
endif( NOT update )
|
||||||
|
|
||||||
|
# write header
|
||||||
|
file( WRITE ${outputFile} "// Do not edit this file, it is autogenerated by CMake.
|
||||||
|
|
||||||
|
#ifndef SHADER_SRC_H
|
||||||
|
#define SHADER_SRC_H
|
||||||
|
|
||||||
|
const unsigned int shaders_number = ${shadersNumber};
|
||||||
|
const char* shaders_src[] =
|
||||||
|
{\n" )
|
||||||
|
|
||||||
|
foreach( inputFile ${inputFiles} )
|
||||||
|
# put the input file name into the output file
|
||||||
|
file( APPEND ${outputFile} "\n// ${inputFile}" )
|
||||||
|
|
||||||
|
# process the input file
|
||||||
|
file( READ ${inputFile} contents )
|
||||||
|
|
||||||
|
# remove /* */ comments
|
||||||
|
string( REGEX REPLACE "/\\*.*\\*/" "" contents "${contents}" )
|
||||||
|
# remove // comments
|
||||||
|
string( REGEX REPLACE "//[^\n]*" "" contents "${contents}" )
|
||||||
|
# remove whitespaces at the beginning of each line
|
||||||
|
string( REGEX REPLACE "\n([\t ])*" "\n" contents "${contents}" )
|
||||||
|
# remove unnecessary spaces
|
||||||
|
string( REGEX REPLACE " *([\\*/+&\\|,=<>\(\)]) *" "\\1" contents "${contents}" )
|
||||||
|
# remove empty lines & wrap every line in "" and add '\n' at the end of each line
|
||||||
|
string( REGEX REPLACE "\n+" "\\\\n\"\n\"" contents "${contents}" )
|
||||||
|
# remove unnecessary " & \n from the beginning and the end of contents
|
||||||
|
string( REGEX REPLACE "^\\\\n\"" "" contents "${contents}" )
|
||||||
|
string( REGEX REPLACE "\"$" "," contents "${contents}" )
|
||||||
|
|
||||||
|
file( APPEND ${outputFile} "${contents}" )
|
||||||
|
endforeach( inputFile ${inputFiles} )
|
||||||
|
|
||||||
|
# write footer
|
||||||
|
file( APPEND ${outputFile} "};
|
||||||
|
#endif /* SHADER_SRC_H */" )
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
So, finally we've got an integrated interactive, push-and-sometimes-shove router, although with a very limited user interface:
|
||||||
|
|
||||||
|
- Edit->Interactive router launches the tool,
|
||||||
|
- while routing: 'V' key places a via,
|
||||||
|
- '+' and '-' keys cycle through available layers,
|
||||||
|
- '/' key switches track posture.
|
||||||
|
|
||||||
|
Via/track dimensions are taken from the netclasses.
|
||||||
|
There are no other options available for the time being - promise to add them soon :)
|
||||||
|
|
||||||
|
Tom
|
|
@ -3,12 +3,65 @@ include_directories(BEFORE ${INC_BEFORE})
|
||||||
include_directories(
|
include_directories(
|
||||||
./dialogs
|
./dialogs
|
||||||
./dialog_about
|
./dialog_about
|
||||||
|
${CAIRO_INCLUDE_DIR}
|
||||||
|
${GLEW_INCLUDE_DIR}
|
||||||
../3d-viewer
|
../3d-viewer
|
||||||
../pcbnew
|
../pcbnew
|
||||||
../polygon
|
../polygon
|
||||||
${INC_AFTER}
|
${INC_AFTER}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Generate header files containing shader programs
|
||||||
|
# Order of input files is significant
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT gal/opengl/shader_src.h
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-DinputFiles="${PROJECT_SOURCE_DIR}/common/gal/opengl/shader.vert\\;${PROJECT_SOURCE_DIR}/common/gal/opengl/shader.frag"
|
||||||
|
-DoutputFile="shader_src.h"
|
||||||
|
-P ${CMAKE_MODULE_PATH}/Shaders.cmake
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/common/gal/opengl
|
||||||
|
COMMENT "Generating headers containing GLSL source code"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
shader_headers ALL
|
||||||
|
DEPENDS gal/opengl/shader_src.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(GAL_SRCS
|
||||||
|
# Common part
|
||||||
|
drawpanel_gal.cpp
|
||||||
|
painter.cpp
|
||||||
|
worksheet_viewitem.cpp
|
||||||
|
gal/graphics_abstraction_layer.cpp
|
||||||
|
gal/stroke_font.cpp
|
||||||
|
gal/color4d.cpp
|
||||||
|
view/wx_view_controls.cpp
|
||||||
|
|
||||||
|
# OpenGL GAL
|
||||||
|
gal/opengl/opengl_gal.cpp
|
||||||
|
gal/opengl/shader.cpp
|
||||||
|
gal/opengl/vertex_item.cpp
|
||||||
|
gal/opengl/vertex_container.cpp
|
||||||
|
gal/opengl/cached_container.cpp
|
||||||
|
gal/opengl/noncached_container.cpp
|
||||||
|
gal/opengl/vertex_manager.cpp
|
||||||
|
gal/opengl/gpu_manager.cpp
|
||||||
|
gal/opengl/opengl_compositor.cpp
|
||||||
|
|
||||||
|
# Cairo GAL
|
||||||
|
gal/cairo/cairo_gal.cpp
|
||||||
|
gal/cairo/cairo_compositor.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(gal STATIC ${GAL_SRCS})
|
||||||
|
add_dependencies(gal shader_headers)
|
||||||
|
|
||||||
|
# Only for win32 cross compilation using MXE
|
||||||
|
if(WIN32 AND MSYS)
|
||||||
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
endif(WIN32 AND MSYS)
|
||||||
|
|
||||||
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
|
||||||
|
@ -95,6 +148,32 @@ set(COMMON_SRCS
|
||||||
zoom.cpp
|
zoom.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enable_language(C CXX ASM)
|
||||||
|
set_source_files_properties(system/fcontext.s PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp")
|
||||||
|
|
||||||
|
set(COMMON_SRCS
|
||||||
|
${COMMON_SRCS}
|
||||||
|
view/view.cpp
|
||||||
|
view/view_item.cpp
|
||||||
|
view/view_group.cpp
|
||||||
|
|
||||||
|
math/math_util.cpp
|
||||||
|
system/fcontext.s
|
||||||
|
|
||||||
|
tool/tool_base.cpp
|
||||||
|
tool/tool_manager.cpp
|
||||||
|
tool/tool_dispatcher.cpp
|
||||||
|
tool/tool_event.cpp
|
||||||
|
tool/tool_interactive.cpp
|
||||||
|
tool/action_manager.cpp
|
||||||
|
tool/context_menu.cpp
|
||||||
|
|
||||||
|
geometry/seg.cpp
|
||||||
|
geometry/shape_line_chain.cpp
|
||||||
|
geometry/shape_collisions.cpp
|
||||||
|
geometry/shape_index.cpp
|
||||||
|
)
|
||||||
|
|
||||||
add_library(common STATIC ${COMMON_SRCS})
|
add_library(common STATIC ${COMMON_SRCS})
|
||||||
|
|
||||||
set(PCB_COMMON_SRCS
|
set(PCB_COMMON_SRCS
|
||||||
|
@ -151,6 +230,10 @@ set(PCB_COMMON_SRCS
|
||||||
fp_lib_table.cpp
|
fp_lib_table.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(PCB_COMMON_SRCS
|
||||||
|
${PCB_COMMON_SRCS}
|
||||||
|
../pcbnew/pcb_painter.cpp
|
||||||
|
)
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
|
|
||||||
#include "../eeschema/dialogs/dialog_schematic_find.h"
|
#include "../eeschema/dialogs/dialog_schematic_find.h"
|
||||||
|
|
||||||
|
|
||||||
|
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
|
||||||
|
|
||||||
|
|
||||||
enum textbox {
|
enum textbox {
|
||||||
ID_TEXTBOX_LIST = 8010
|
ID_TEXTBOX_LIST = 8010
|
||||||
};
|
};
|
||||||
|
@ -190,8 +194,28 @@ bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText )
|
||||||
wxCHECK_MSG( IsReplaceable(), false,
|
wxCHECK_MSG( IsReplaceable(), false,
|
||||||
wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) );
|
wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) );
|
||||||
|
|
||||||
return aText.Replace( aSearchData.GetFindString(),
|
wxString searchString = (aSearchData.GetFlags() & wxFR_MATCHCASE) ? aText.Upper() : aText;
|
||||||
aSearchData.GetReplaceString(), false ) != 0;
|
|
||||||
|
int result = searchString.Find( (aSearchData.GetFlags() & wxFR_MATCHCASE) ?
|
||||||
|
aSearchData.GetFindString() :
|
||||||
|
aSearchData.GetFindString().Upper() );
|
||||||
|
|
||||||
|
if( result == wxNOT_FOUND )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxString prefix = aText.Left( result );
|
||||||
|
wxString suffix;
|
||||||
|
|
||||||
|
if( aSearchData.GetFindString().length() + result < aText.length() )
|
||||||
|
suffix = aText.Right( aText.length() - ( aSearchData.GetFindString().length() + result ) );
|
||||||
|
|
||||||
|
wxLogTrace( traceFindReplace, wxT( "Replacing '%s', prefix '%s', replace '%s', suffix '%s'." ),
|
||||||
|
GetChars( aText ), GetChars( prefix ), GetChars( aSearchData.GetReplaceString() ),
|
||||||
|
GetChars( suffix ) );
|
||||||
|
|
||||||
|
aText = prefix + aSearchData.GetReplaceString() + suffix;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,6 +246,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 @@
|
||||||
#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>
|
||||||
|
@ -42,10 +43,11 @@
|
||||||
#include <kicad_device_context.h>
|
#include <kicad_device_context.h>
|
||||||
#include <dialog_helpers.h>
|
#include <dialog_helpers.h>
|
||||||
#include <base_units.h>
|
#include <base_units.h>
|
||||||
#include <vector2d.h>
|
#include <math/box2.h>
|
||||||
|
|
||||||
#include <wx/fontdlg.h>
|
#include <wx/fontdlg.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition for enabling and disabling scroll bar setting trace output. See the
|
* Definition for enabling and disabling scroll bar setting trace output. See the
|
||||||
|
@ -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;
|
||||||
|
@ -224,6 +228,12 @@ void EDA_DRAW_FRAME::SkipNextLeftButtonReleaseEvent()
|
||||||
void EDA_DRAW_FRAME::OnToggleGridState( wxCommandEvent& aEvent )
|
void EDA_DRAW_FRAME::OnToggleGridState( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
SetGridVisibility( !IsGridVisible() );
|
SetGridVisibility( !IsGridVisible() );
|
||||||
|
if( m_galCanvasActive )
|
||||||
|
{
|
||||||
|
m_galCanvas->GetGAL()->SetGridVisibility( IsGridVisible() );
|
||||||
|
m_galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
|
||||||
|
}
|
||||||
|
|
||||||
m_canvas->Refresh();
|
m_canvas->Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +386,15 @@ void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event )
|
||||||
m_LastGridSizeId = id - ID_POPUP_GRID_LEVEL_1000;
|
m_LastGridSizeId = id - ID_POPUP_GRID_LEVEL_1000;
|
||||||
screen->SetGrid( id );
|
screen->SetGrid( id );
|
||||||
SetCrossHairPosition( RefPos( true ) );
|
SetCrossHairPosition( RefPos( true ) );
|
||||||
Refresh();
|
|
||||||
|
if( m_galCanvasActive )
|
||||||
|
{
|
||||||
|
m_galCanvas->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x,
|
||||||
|
screen->GetGrid().m_Size.y ) );
|
||||||
|
m_galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_canvas->Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -403,7 +421,21 @@ void EDA_DRAW_FRAME::OnSelectZoom( wxCommandEvent& event )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GetScreen()->SetZoom( selectedZoom );
|
GetScreen()->SetZoom( selectedZoom );
|
||||||
RedrawScreen( GetScrollCenterPosition(), false );
|
|
||||||
|
if( m_galCanvasActive )
|
||||||
|
{
|
||||||
|
// Apply computed view settings to GAL
|
||||||
|
KIGFX::VIEW* view = m_galCanvas->GetView();
|
||||||
|
KIGFX::GAL* gal = m_galCanvas->GetGAL();
|
||||||
|
|
||||||
|
double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
|
||||||
|
double zoom = 1.0 / ( zoomFactor * GetZoom() );
|
||||||
|
|
||||||
|
view->SetScale( zoom );
|
||||||
|
m_galCanvas->Refresh();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
RedrawScreen( GetScrollCenterPosition(), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,7 +770,7 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
DSIZE clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );
|
DSIZE clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );
|
||||||
|
|
||||||
// Full drawing or "page" rectangle in internal units
|
// Full drawing or "page" rectangle in internal units
|
||||||
DBOX pageRectIU( 0, 0, GetPageSizeIU().x, GetPageSizeIU().y );
|
DBOX pageRectIU( wxPoint( 0, 0 ), wxSize( GetPageSizeIU().x, GetPageSizeIU().y ) );
|
||||||
|
|
||||||
// The upper left corner of the client rectangle in internal units.
|
// The upper left corner of the client rectangle in internal units.
|
||||||
double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
|
double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
|
||||||
|
@ -748,11 +780,11 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
if( screen->m_Center )
|
if( screen->m_Center )
|
||||||
{
|
{
|
||||||
// half page offset.
|
// half page offset.
|
||||||
xIU += pageRectIU.width / 2.0;
|
xIU += pageRectIU.GetWidth() / 2.0;
|
||||||
yIU += pageRectIU.height / 2.0;
|
yIU += pageRectIU.GetHeight() / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBOX clientRectIU( xIU, yIU, clientSizeIU.x, clientSizeIU.y );
|
DBOX clientRectIU( wxPoint( xIU, yIU ), wxSize( clientSizeIU.x, clientSizeIU.y ) );
|
||||||
wxPoint centerPositionIU;
|
wxPoint centerPositionIU;
|
||||||
|
|
||||||
// put "int" limits on the clientRect
|
// put "int" limits on the clientRect
|
||||||
|
@ -765,13 +797,13 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
if( clientRectIU.GetBottom() > VIRT_MAX )
|
if( clientRectIU.GetBottom() > VIRT_MAX )
|
||||||
clientRectIU.MoveBottomTo( VIRT_MAX );
|
clientRectIU.MoveBottomTo( VIRT_MAX );
|
||||||
|
|
||||||
centerPositionIU.x = KiROUND( clientRectIU.x + clientRectIU.width/2 );
|
centerPositionIU.x = KiROUND( clientRectIU.GetX() + clientRectIU.GetWidth() / 2 );
|
||||||
centerPositionIU.y = KiROUND( clientRectIU.y + clientRectIU.height/2 );
|
centerPositionIU.y = KiROUND( clientRectIU.GetY() + clientRectIU.GetHeight() / 2 );
|
||||||
|
|
||||||
if( screen->m_Center )
|
if( screen->m_Center )
|
||||||
{
|
{
|
||||||
centerPositionIU.x -= KiROUND( pageRectIU.width / 2.0 );
|
centerPositionIU.x -= KiROUND( pageRectIU.GetWidth() / 2.0 );
|
||||||
centerPositionIU.y -= KiROUND( pageRectIU.height / 2.0 );
|
centerPositionIU.y -= KiROUND( pageRectIU.GetHeight() / 2.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSIZE virtualSizeIU;
|
DSIZE virtualSizeIU;
|
||||||
|
@ -782,26 +814,26 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double pageCenterX = pageRectIU.x + ( pageRectIU.width / 2 );
|
double pageCenterX = pageRectIU.GetX() + ( pageRectIU.GetWidth() / 2 );
|
||||||
double clientCenterX = clientRectIU.x + ( clientRectIU.width / 2 );
|
double clientCenterX = clientRectIU.GetX() + ( clientRectIU.GetWidth() / 2 );
|
||||||
|
|
||||||
if( clientRectIU.width > pageRectIU.width )
|
if( clientRectIU.GetWidth() > pageRectIU.GetWidth() )
|
||||||
{
|
{
|
||||||
if( pageCenterX > clientCenterX )
|
if( pageCenterX > clientCenterX )
|
||||||
virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
|
virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
|
||||||
else if( pageCenterX < clientCenterX )
|
else if( pageCenterX < clientCenterX )
|
||||||
virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
|
virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
|
||||||
else
|
else
|
||||||
virtualSizeIU.x = clientRectIU.width;
|
virtualSizeIU.x = clientRectIU.GetWidth();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( pageCenterX > clientCenterX )
|
if( pageCenterX > clientCenterX )
|
||||||
virtualSizeIU.x = pageRectIU.width + ( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
|
virtualSizeIU.x = pageRectIU.GetWidth() + ( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
|
||||||
else if( pageCenterX < clientCenterX )
|
else if( pageCenterX < clientCenterX )
|
||||||
virtualSizeIU.x = pageRectIU.width + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
|
virtualSizeIU.x = pageRectIU.GetWidth() + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
|
||||||
else
|
else
|
||||||
virtualSizeIU.x = pageRectIU.width;
|
virtualSizeIU.x = pageRectIU.GetWidth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,28 +843,28 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double pageCenterY = pageRectIU.y + ( pageRectIU.height / 2 );
|
double pageCenterY = pageRectIU.GetY() + ( pageRectIU.GetHeight() / 2 );
|
||||||
double clientCenterY = clientRectIU.y + ( clientRectIU.height / 2 );
|
double clientCenterY = clientRectIU.GetY() + ( clientRectIU.GetHeight() / 2 );
|
||||||
|
|
||||||
if( clientRectIU.height > pageRectIU.height )
|
if( clientRectIU.GetHeight() > pageRectIU.GetHeight() )
|
||||||
{
|
{
|
||||||
if( pageCenterY > clientCenterY )
|
if( pageCenterY > clientCenterY )
|
||||||
virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
|
virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
|
||||||
else if( pageCenterY < clientCenterY )
|
else if( pageCenterY < clientCenterY )
|
||||||
virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
|
virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
|
||||||
else
|
else
|
||||||
virtualSizeIU.y = clientRectIU.height;
|
virtualSizeIU.y = clientRectIU.GetHeight();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( pageCenterY > clientCenterY )
|
if( pageCenterY > clientCenterY )
|
||||||
virtualSizeIU.y = pageRectIU.height +
|
virtualSizeIU.y = pageRectIU.GetHeight() +
|
||||||
( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
|
( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
|
||||||
else if( pageCenterY < clientCenterY )
|
else if( pageCenterY < clientCenterY )
|
||||||
virtualSizeIU.y = pageRectIU.height +
|
virtualSizeIU.y = pageRectIU.GetHeight() +
|
||||||
( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
|
( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
|
||||||
else
|
else
|
||||||
virtualSizeIU.y = pageRectIU.height;
|
virtualSizeIU.y = pageRectIU.GetHeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,8 +879,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.width ) / 2.0 );
|
screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.GetWidth() ) / 2.0 );
|
||||||
screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.height ) / 2.0 );
|
screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.GetHeight() ) / 2.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always set scrollbar pixels per unit to 1 unless you want the zoom
|
/* Always set scrollbar pixels per unit to 1 unless you want the zoom
|
||||||
|
@ -867,8 +899,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
// center position at the center of client rectangle.
|
// center position at the center of client rectangle.
|
||||||
SetScrollCenterPosition( centerPositionIU );
|
SetScrollCenterPosition( centerPositionIU );
|
||||||
|
|
||||||
double posX = centerPositionIU.x - clientRectIU.width /2.0 - screen->m_DrawOrg.x;
|
double posX = centerPositionIU.x - clientRectIU.GetWidth() / 2.0 - screen->m_DrawOrg.x;
|
||||||
double posY = centerPositionIU.y - clientRectIU.height/2.0 - screen->m_DrawOrg.y;
|
double posY = centerPositionIU.y - clientRectIU.GetHeight() / 2.0 - screen->m_DrawOrg.y;
|
||||||
|
|
||||||
// Convert scroll bar position to device units.
|
// Convert scroll bar position to device units.
|
||||||
posX = KiROUND( posX * scale );
|
posX = KiROUND( posX * scale );
|
||||||
|
@ -919,6 +951,61 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
||||||
screen->m_ScrollbarPos.y, noRefresh );
|
screen->m_ScrollbarPos.y, noRefresh );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
|
||||||
|
{
|
||||||
|
KIGFX::VIEW* view = m_galCanvas->GetView();
|
||||||
|
KIGFX::GAL* gal = m_galCanvas->GetGAL();
|
||||||
|
|
||||||
|
double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
|
||||||
|
|
||||||
|
// Display the same view after canvas switching
|
||||||
|
if( aEnable )
|
||||||
|
{
|
||||||
|
BASE_SCREEN* screen = GetScreen();
|
||||||
|
|
||||||
|
// Switch to GAL rendering
|
||||||
|
if( !m_galCanvasActive )
|
||||||
|
{
|
||||||
|
// Set up viewport
|
||||||
|
double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() );
|
||||||
|
view->SetScale( zoom );
|
||||||
|
view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up grid settings
|
||||||
|
gal->SetGridVisibility( IsGridVisible() );
|
||||||
|
gal->SetGridSize( VECTOR2D( screen->GetGridSize().x, screen->GetGridSize().y ) );
|
||||||
|
gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Switch to standard rendering
|
||||||
|
if( m_galCanvasActive )
|
||||||
|
{
|
||||||
|
// Change view settings only if GAL was active previously
|
||||||
|
double zoom = 1.0 / ( zoomFactor * view->GetScale() );
|
||||||
|
m_canvas->SetZoom( zoom );
|
||||||
|
|
||||||
|
VECTOR2D center = view->GetCenter();
|
||||||
|
RedrawScreen( wxPoint( center.x, center.y ), false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_canvas->SetEvtHandlerEnabled( !aEnable );
|
||||||
|
m_galCanvas->SetEvtHandlerEnabled( aEnable );
|
||||||
|
|
||||||
|
// Switch panes
|
||||||
|
m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable );
|
||||||
|
m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable );
|
||||||
|
m_auimgr.Update();
|
||||||
|
|
||||||
|
m_galCanvasActive = aEnable;
|
||||||
|
|
||||||
|
if( aEnable )
|
||||||
|
m_galCanvas->SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
//-----< BASE_SCREEN API moved here >--------------------------------------------
|
//-----< BASE_SCREEN API moved here >--------------------------------------------
|
||||||
|
|
||||||
wxPoint EDA_DRAW_FRAME::GetCrossHairPosition( bool aInvertY ) const
|
wxPoint EDA_DRAW_FRAME::GetCrossHairPosition( bool aInvertY ) const
|
||||||
|
@ -986,4 +1073,3 @@ void EDA_DRAW_FRAME::SetScrollCenterPosition( const wxPoint& aPoint )
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----</BASE_SCREEN API moved here >--------------------------------------------
|
//-----</BASE_SCREEN API moved here >--------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
@ -84,10 +85,17 @@ END_EVENT_TABLE()
|
||||||
|
|
||||||
EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id,
|
EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id,
|
||||||
const wxPoint& pos, const wxSize& size ) :
|
const wxPoint& pos, const wxSize& size ) :
|
||||||
|
#if wxCHECK_VERSION( 2, 9, 5 )
|
||||||
|
wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL )
|
||||||
|
#else
|
||||||
wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL | wxALWAYS_SHOW_SB )
|
wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL | wxALWAYS_SHOW_SB )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
wxASSERT( parent );
|
wxASSERT( parent );
|
||||||
|
|
||||||
|
#if wxCHECK_VERSION( 2, 9, 5 )
|
||||||
|
ShowScrollbars( wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS );
|
||||||
|
#endif
|
||||||
m_scrollIncrementX = std::min( size.x / 8, 10 );
|
m_scrollIncrementX = std::min( size.x / 8, 10 );
|
||||||
m_scrollIncrementY = std::min( size.y / 8, 10 );
|
m_scrollIncrementY = std::min( size.y / 8, 10 );
|
||||||
|
|
||||||
|
@ -288,6 +296,19 @@ void EDA_DRAW_PANEL::RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL::Refresh( bool eraseBackground, const wxRect* rect )
|
||||||
|
{
|
||||||
|
if( GetParent()->IsGalCanvasActive() )
|
||||||
|
{
|
||||||
|
GetParent()->GetGalCanvas()->Refresh();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxScrolledWindow::Refresh( eraseBackground, rect );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxPoint EDA_DRAW_PANEL::GetScreenCenterLogicalPosition()
|
wxPoint EDA_DRAW_PANEL::GetScreenCenterLogicalPosition()
|
||||||
{
|
{
|
||||||
wxSize size = GetClientSize() / 2;
|
wxSize size = GetClientSize() / 2;
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* 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/filename.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>
|
||||||
|
|
||||||
|
#include <tool/tool_dispatcher.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
#include <profile.h>
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
|
||||||
|
#define METRIC_UNIT_LENGTH (1e9)
|
||||||
|
|
||||||
|
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_gal = NULL;
|
||||||
|
m_currentGal = GAL_TYPE_NONE;
|
||||||
|
m_view = NULL;
|
||||||
|
m_painter = NULL;
|
||||||
|
m_eventDispatcher = NULL;
|
||||||
|
|
||||||
|
SwitchBackend( aGalType );
|
||||||
|
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
|
||||||
|
|
||||||
|
// Initial display settings
|
||||||
|
m_gal->SetLookAtPoint( VECTOR2D( 0, 0 ) );
|
||||||
|
m_gal->SetZoomFactor( 1.0 );
|
||||||
|
m_gal->ComputeWorldScreenMatrix();
|
||||||
|
|
||||||
|
m_painter = new KIGFX::PCB_PAINTER( m_gal );
|
||||||
|
|
||||||
|
m_view = new KIGFX::VIEW( true );
|
||||||
|
m_view->SetPainter( m_painter );
|
||||||
|
m_view->SetGAL( m_gal );
|
||||||
|
|
||||||
|
m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this );
|
||||||
|
|
||||||
|
Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
|
||||||
|
Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this );
|
||||||
|
|
||||||
|
/* Generic events for the Tool Dispatcher */
|
||||||
|
Connect( wxEVT_MOTION, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_LEFT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_LEFT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_RIGHT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_RIGHT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_MIDDLE_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_MIDDLE_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) );
|
||||||
|
Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this );
|
||||||
|
Connect( KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE,
|
||||||
|
wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
|
||||||
|
|
||||||
|
m_refreshTimer.SetOwner( this );
|
||||||
|
Connect( wxEVT_TIMER, wxTimerEventHandler( EDA_DRAW_PANEL_GAL::onRefreshTimer ), NULL, this );
|
||||||
|
|
||||||
|
this->SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
|
||||||
|
{
|
||||||
|
m_pendingRefresh = false;
|
||||||
|
m_lastRefresh = wxGetLocalTimeMillis();
|
||||||
|
|
||||||
|
m_gal->BeginDrawing();
|
||||||
|
m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
|
||||||
|
m_gal->ClearScreen();
|
||||||
|
|
||||||
|
m_view->ClearTargets();
|
||||||
|
// Grid has to be redrawn only when the NONCACHED target is redrawn
|
||||||
|
if( m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) )
|
||||||
|
m_gal->DrawGrid();
|
||||||
|
m_view->Redraw();
|
||||||
|
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
|
||||||
|
|
||||||
|
m_gal->EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_gal->ResizeScreen( aEvent.GetSize().x, aEvent.GetSize().y );
|
||||||
|
m_view->MarkTargetDirty( KIGFX::TARGET_CACHED );
|
||||||
|
m_view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent )
|
||||||
|
{
|
||||||
|
wxPaintEvent redrawEvent;
|
||||||
|
wxPostEvent( this, redrawEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
|
||||||
|
{
|
||||||
|
if( m_pendingRefresh )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxLongLong t = wxGetLocalTimeMillis();
|
||||||
|
wxLongLong delta = t - m_lastRefresh;
|
||||||
|
|
||||||
|
if( delta >= MinRefreshPeriod )
|
||||||
|
{
|
||||||
|
wxPaintEvent redrawEvent;
|
||||||
|
wxPostEvent( this, redrawEvent );
|
||||||
|
m_pendingRefresh = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// One shot timer
|
||||||
|
m_refreshTimer.Start( ( MinRefreshPeriod - delta ).ToLong(), true );
|
||||||
|
m_pendingRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
|
||||||
|
{
|
||||||
|
// Protect from refreshing during backend switch
|
||||||
|
m_pendingRefresh = true;
|
||||||
|
m_refreshTimer.Stop();
|
||||||
|
|
||||||
|
// Do not do anything if the currently used GAL is correct
|
||||||
|
if( aGalType == m_currentGal && m_gal != NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete m_gal;
|
||||||
|
|
||||||
|
switch( aGalType )
|
||||||
|
{
|
||||||
|
case GAL_TYPE_OPENGL:
|
||||||
|
m_gal = new KIGFX::OPENGL_GAL( this, this, this );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GAL_TYPE_CAIRO:
|
||||||
|
m_gal = new KIGFX::CAIRO_GAL( this, this, this );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GAL_TYPE_NONE:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gal->SetWorldUnitLength( 1.0 / METRIC_UNIT_LENGTH * 2.54 ); // 1 inch in nanometers
|
||||||
|
m_gal->SetScreenDPI( 106 ); // Display resolution setting
|
||||||
|
m_gal->ComputeWorldScreenMatrix();
|
||||||
|
|
||||||
|
wxSize size = GetClientSize();
|
||||||
|
m_gal->ResizeScreen( size.GetX(), size.GetY() );
|
||||||
|
|
||||||
|
if( m_painter )
|
||||||
|
m_painter->SetGAL( m_gal );
|
||||||
|
|
||||||
|
if( m_view )
|
||||||
|
{
|
||||||
|
m_view->SetGAL( m_gal );
|
||||||
|
m_view->RecacheAllItems( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentGal = aGalType;
|
||||||
|
m_pendingRefresh = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::onEvent( wxEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_eventDispatcher )
|
||||||
|
{
|
||||||
|
aEvent.Skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_eventDispatcher->DispatchWxEvent( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::onEnter( wxEvent& aEvent )
|
||||||
|
{
|
||||||
|
// Getting focus is necessary in order to receive key events properly
|
||||||
|
SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_DRAW_PANEL_GAL::skipEvent( wxEvent& aEvent )
|
||||||
|
{
|
||||||
|
// This is necessary for CHAR_HOOK event to generate KEY_UP and KEY_DOWN events
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
|
@ -32,6 +32,13 @@
|
||||||
#include <trigo.h> // RotatePoint
|
#include <trigo.h> // RotatePoint
|
||||||
#include <class_drawpanel.h> // EDA_DRAW_PANEL
|
#include <class_drawpanel.h> // EDA_DRAW_PANEL
|
||||||
|
|
||||||
|
// until bzr rev 4410, Y position of vertical justification
|
||||||
|
// of multiline texts was incorrectly calculated for BOTTOM
|
||||||
|
// and CENTER vertical justification. (Only the first line was justified)
|
||||||
|
// If this line is left uncommented, the bug is fixed, but
|
||||||
|
// creates a (very minor) issue for existing texts, mainly in Pcbnew
|
||||||
|
// because the text position is sometimes critical.
|
||||||
|
#define FIX_MULTILINE_VERT_JUSTIF
|
||||||
|
|
||||||
// Conversion to application internal units defined at build time.
|
// Conversion to application internal units defined at build time.
|
||||||
#if defined( PCBNEW )
|
#if defined( PCBNEW )
|
||||||
|
@ -90,6 +97,16 @@ int EDA_TEXT::LenSize( const wxString& aLine ) const
|
||||||
return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold );
|
return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetInterline
|
||||||
|
* return the distance between 2 text lines
|
||||||
|
* has meaning only for multiline texts
|
||||||
|
*/
|
||||||
|
int EDA_TEXT::GetInterline( int aTextThickness ) const
|
||||||
|
{
|
||||||
|
int thickness = aTextThickness <= 0 ? m_Thickness : aTextThickness;
|
||||||
|
return (( m_Size.y * 14 ) / 10) + thickness;
|
||||||
|
}
|
||||||
|
|
||||||
EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
||||||
{
|
{
|
||||||
|
@ -98,6 +115,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
||||||
wxArrayString* list = NULL;
|
wxArrayString* list = NULL;
|
||||||
wxString text = m_Text;
|
wxString text = m_Text;
|
||||||
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
|
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
|
||||||
|
int linecount = 1;
|
||||||
|
|
||||||
if( m_MultilineAllowed )
|
if( m_MultilineAllowed )
|
||||||
{
|
{
|
||||||
|
@ -109,12 +127,14 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
||||||
text = list->Item( aLine );
|
text = list->Item( aLine );
|
||||||
else
|
else
|
||||||
text = list->Item( 0 );
|
text = list->Item( 0 );
|
||||||
|
|
||||||
|
linecount = list->GetCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the H and V size
|
// calculate the H and V size
|
||||||
int dx = LenSize( text );
|
int dx = LenSize( text );
|
||||||
int dy = GetInterline();
|
int dy = GetInterline( aThickness );
|
||||||
|
|
||||||
/* Creates bounding box (rectangle) for an horizontal text */
|
/* Creates bounding box (rectangle) for an horizontal text */
|
||||||
wxSize textsize = wxSize( dx, dy );
|
wxSize textsize = wxSize( dx, dy );
|
||||||
|
@ -175,7 +195,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GR_TEXT_VJUSTIFY_CENTER:
|
case GR_TEXT_VJUSTIFY_CENTER:
|
||||||
rect.SetY( rect.GetY() - (dy / 2) );
|
rect.SetY( rect.GetY() - ( dy / 2) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GR_TEXT_VJUSTIFY_BOTTOM:
|
case GR_TEXT_VJUSTIFY_BOTTOM:
|
||||||
|
@ -183,6 +203,30 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( linecount > 1 )
|
||||||
|
{
|
||||||
|
#ifdef FIX_MULTILINE_VERT_JUSTIF
|
||||||
|
int yoffset;
|
||||||
|
linecount -= 1;
|
||||||
|
|
||||||
|
switch( m_VJustify )
|
||||||
|
{
|
||||||
|
case GR_TEXT_VJUSTIFY_TOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_VJUSTIFY_CENTER:
|
||||||
|
yoffset = linecount * GetInterline() / 2;
|
||||||
|
rect.SetY( rect.GetY() - yoffset );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_VJUSTIFY_BOTTOM:
|
||||||
|
yoffset = linecount * GetInterline( aThickness );
|
||||||
|
rect.SetY( rect.GetY() - yoffset );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
rect.Inflate( thickness / 2 );
|
rect.Inflate( thickness / 2 );
|
||||||
rect.Normalize(); // Make h and v sizes always >= 0
|
rect.Normalize(); // Make h and v sizes always >= 0
|
||||||
|
|
||||||
|
@ -227,15 +271,31 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset,
|
||||||
|
|
||||||
offset.y = GetInterline();
|
offset.y = GetInterline();
|
||||||
|
|
||||||
|
#ifdef FIX_MULTILINE_VERT_JUSTIF
|
||||||
|
if( list->Count() > 1 )
|
||||||
|
{
|
||||||
|
switch( m_VJustify )
|
||||||
|
{
|
||||||
|
case GR_TEXT_VJUSTIFY_TOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_VJUSTIFY_CENTER:
|
||||||
|
pos.y -= ( list->Count() - 1 ) * offset.y / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_VJUSTIFY_BOTTOM:
|
||||||
|
pos.y -= ( list->Count() - 1 ) * offset.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
RotatePoint( &offset, m_Orient );
|
RotatePoint( &offset, m_Orient );
|
||||||
|
|
||||||
for( unsigned i = 0; i<list->Count(); i++ )
|
for( unsigned i = 0; i<list->Count(); i++ )
|
||||||
{
|
{
|
||||||
wxString txt = list->Item( i );
|
wxString txt = list->Item( i );
|
||||||
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
||||||
aDrawMode, aFillMode,
|
aDrawMode, aFillMode, txt, pos );
|
||||||
i ? UNSPECIFIED_COLOR : aAnchor_color,
|
|
||||||
txt, pos );
|
|
||||||
pos += offset;
|
pos += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,15 +303,21 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
||||||
aDrawMode, aFillMode,
|
aDrawMode, aFillMode, m_Text, m_Pos );
|
||||||
aAnchor_color, m_Text, m_Pos );
|
|
||||||
|
// Draw text anchor, if requested
|
||||||
|
if( aAnchor_color != UNSPECIFIED_COLOR )
|
||||||
|
{
|
||||||
|
GRDrawAnchor( aClipBox, aDC,
|
||||||
|
m_Pos.x + aOffset.x, m_Pos.y + aOffset.y,
|
||||||
|
DIM_ANCRE_TEXTE, aAnchor_color );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EDA_TEXT::drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
void EDA_TEXT::drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
||||||
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
||||||
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
||||||
EDA_COLOR_T aAnchor_color,
|
|
||||||
wxString& aText, wxPoint aPos )
|
wxString& aText, wxPoint aPos )
|
||||||
{
|
{
|
||||||
int width = m_Thickness;
|
int width = m_Thickness;
|
||||||
|
@ -262,14 +328,6 @@ void EDA_TEXT::drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
||||||
if( aDrawMode != UNSPECIFIED_DRAWMODE )
|
if( aDrawMode != UNSPECIFIED_DRAWMODE )
|
||||||
GRSetDrawMode( aDC, aDrawMode );
|
GRSetDrawMode( aDC, aDrawMode );
|
||||||
|
|
||||||
// Draw text anchor, if requested
|
|
||||||
if( aAnchor_color != UNSPECIFIED_COLOR )
|
|
||||||
{
|
|
||||||
GRDrawAnchor( aClipBox, aDC,
|
|
||||||
aPos.x + aOffset.x, aPos.y + aOffset.y,
|
|
||||||
DIM_ANCRE_TEXTE, aAnchor_color );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aFillMode == SKETCH )
|
if( aFillMode == SKETCH )
|
||||||
width = -width;
|
width = -width;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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:O//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 cairo_compositor.cpp
|
||||||
|
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
|
||||||
|
* later compositing into a single image (Cairo flavour).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/cairo/cairo_compositor.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
|
||||||
|
m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CAIRO_COMPOSITOR::~CAIRO_COMPOSITOR()
|
||||||
|
{
|
||||||
|
clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::Initialize()
|
||||||
|
{
|
||||||
|
// Nothing has to be done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
|
||||||
|
{
|
||||||
|
clean();
|
||||||
|
|
||||||
|
m_width = aWidth;
|
||||||
|
m_height = aHeight;
|
||||||
|
|
||||||
|
m_stride = cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, m_width );
|
||||||
|
m_bufferSize = m_stride * m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int CAIRO_COMPOSITOR::CreateBuffer()
|
||||||
|
{
|
||||||
|
// Pixel storage
|
||||||
|
BitmapPtr bitmap( new unsigned int[m_bufferSize] );
|
||||||
|
|
||||||
|
memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
|
||||||
|
|
||||||
|
// Create the Cairo surface
|
||||||
|
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||||
|
(unsigned char*) bitmap.get(),
|
||||||
|
CAIRO_FORMAT_ARGB32, m_width,
|
||||||
|
m_height, m_stride );
|
||||||
|
cairo_t* context = cairo_create( surface );
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
cairo_status_t status = cairo_status( context );
|
||||||
|
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
|
||||||
|
// Set default settings for the buffer
|
||||||
|
cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
|
||||||
|
cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
|
||||||
|
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
|
||||||
|
|
||||||
|
// Use the same transformation matrix as the main context
|
||||||
|
cairo_get_matrix( m_mainContext, &m_matrix );
|
||||||
|
cairo_set_matrix( context, &m_matrix );
|
||||||
|
|
||||||
|
// Store the new buffer
|
||||||
|
CAIRO_BUFFER buffer = { context, surface, bitmap };
|
||||||
|
m_buffers.push_back( buffer );
|
||||||
|
|
||||||
|
return usedBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
|
||||||
|
|
||||||
|
// Get currently used transformation matrix, so it can be applied to the new buffer
|
||||||
|
cairo_get_matrix( *m_currentContext, &m_matrix );
|
||||||
|
|
||||||
|
m_current = aBufferHandle - 1;
|
||||||
|
*m_currentContext = m_buffers[m_current].context;
|
||||||
|
|
||||||
|
// Apply the current transformation matrix
|
||||||
|
cairo_set_matrix( *m_currentContext, &m_matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::ClearBuffer()
|
||||||
|
{
|
||||||
|
// Clear the pixel storage
|
||||||
|
memset( m_buffers[m_current].bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
|
||||||
|
|
||||||
|
// Reset the transformation matrix, so it is possible to composite images using
|
||||||
|
// screen coordinates instead of world coordinates
|
||||||
|
cairo_get_matrix( m_mainContext, &m_matrix );
|
||||||
|
cairo_identity_matrix( m_mainContext );
|
||||||
|
|
||||||
|
// Draw the selected buffer contents
|
||||||
|
cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 );
|
||||||
|
cairo_paint( m_mainContext );
|
||||||
|
|
||||||
|
// Restore the transformation matrix
|
||||||
|
cairo_set_matrix( m_mainContext, &m_matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_COMPOSITOR::clean()
|
||||||
|
{
|
||||||
|
CAIRO_BUFFERS::const_iterator it;
|
||||||
|
|
||||||
|
for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
|
||||||
|
{
|
||||||
|
cairo_destroy( it->context );
|
||||||
|
cairo_surface_destroy( it->surface );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffers.clear();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Color 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/color4d.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
COLOR4D::COLOR4D( EDA_COLOR_T aColor )
|
||||||
|
{
|
||||||
|
r = g_ColorRefs[aColor].m_Red / 255.0;
|
||||||
|
g = g_ColorRefs[aColor].m_Green / 255.0;
|
||||||
|
b = g_ColorRefs[aColor].m_Blue / 255.0;
|
||||||
|
a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WX_COMPATIBILITY
|
||||||
|
COLOR4D::COLOR4D( const wxColour& aColor )
|
||||||
|
{
|
||||||
|
r = aColor.Red();
|
||||||
|
g = aColor.Green();
|
||||||
|
b = aColor.Blue();
|
||||||
|
a = aColor.Alpha();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
const bool COLOR4D::operator==( const COLOR4D& aColor )
|
||||||
|
{
|
||||||
|
return a == aColor.a && r == aColor.r && g == aColor.g && b == aColor.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool COLOR4D::operator!=( const COLOR4D& aColor )
|
||||||
|
{
|
||||||
|
return a != aColor.a || r != aColor.r || g != aColor.g || b != aColor.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void COLOR4D::ToHSV( double& aOutH, double& aOutS, double& aOutV ) const
|
||||||
|
{
|
||||||
|
double min, max, delta;
|
||||||
|
|
||||||
|
min = r < g ? r : g;
|
||||||
|
min = min < b ? min : b;
|
||||||
|
|
||||||
|
max = r > g ? r : g;
|
||||||
|
max = max > b ? max : b;
|
||||||
|
|
||||||
|
aOutV = max; // v
|
||||||
|
delta = max - min;
|
||||||
|
|
||||||
|
if( max > 0.0 )
|
||||||
|
{
|
||||||
|
aOutS = ( delta / max ); // s
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// r = g = b = 0 // s = 0, v is undefined
|
||||||
|
aOutS = 0.0;
|
||||||
|
aOutH = NAN; // its now undefined
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( r >= max ) // > is bogus, just keeps compiler happy
|
||||||
|
aOutH = ( g - b ) / delta; // between yellow & magenta
|
||||||
|
else if( g >= max )
|
||||||
|
aOutH = 2.0 + ( b - r ) / delta; // between cyan & yellow
|
||||||
|
else
|
||||||
|
aOutH = 4.0 + ( r - g ) / delta; // between magenta & cyan
|
||||||
|
|
||||||
|
aOutH *= 60.0; // degrees
|
||||||
|
|
||||||
|
if( aOutH < 0.0 )
|
||||||
|
aOutH += 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void COLOR4D::FromHSV( double aInH, double aInS, double aInV )
|
||||||
|
{
|
||||||
|
double hh, p, q, t, ff;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
if( aInS <= 0.0 ) // < is bogus, just shuts up warnings
|
||||||
|
{
|
||||||
|
r = aInV;
|
||||||
|
g = aInV;
|
||||||
|
b = aInV;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hh = aInH;
|
||||||
|
|
||||||
|
if( hh >= 360.0 )
|
||||||
|
hh = 0.0;
|
||||||
|
|
||||||
|
hh /= 60.0;
|
||||||
|
|
||||||
|
i = (long) hh;
|
||||||
|
ff = hh - i;
|
||||||
|
|
||||||
|
p = aInV * ( 1.0 - aInS );
|
||||||
|
q = aInV * ( 1.0 - ( aInS * ff ) );
|
||||||
|
t = aInV * ( 1.0 - ( aInS * ( 1.0 - ff ) ) );
|
||||||
|
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r = aInV;
|
||||||
|
g = t;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
r = q;
|
||||||
|
g = aInV;
|
||||||
|
b = p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
r = p;
|
||||||
|
g = aInV;
|
||||||
|
b = t;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
r = p;
|
||||||
|
g = q;
|
||||||
|
b = aInV;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
r = t;
|
||||||
|
g = p;
|
||||||
|
b = aInV;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
default:
|
||||||
|
r = aInV;
|
||||||
|
g = p;
|
||||||
|
b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
COLOR4D& COLOR4D::Saturate( double aFactor )
|
||||||
|
{
|
||||||
|
double h, s, v;
|
||||||
|
|
||||||
|
ToHSV( h, s, v );
|
||||||
|
FromHSV( h, aFactor, 1.0 );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
GAL::GAL() :
|
||||||
|
strokeFont( this )
|
||||||
|
{
|
||||||
|
// Set the default values for the internal variables
|
||||||
|
SetIsFill( false );
|
||||||
|
SetIsStroke( true );
|
||||||
|
SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
|
||||||
|
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
|
||||||
|
SetZoomFactor( 1.0 );
|
||||||
|
SetDepthRange( VECTOR2D( GAL::MIN_DEPTH, GAL::MAX_DEPTH ) );
|
||||||
|
SetFlip( false, false );
|
||||||
|
SetLineWidth( 1.0 );
|
||||||
|
|
||||||
|
// Set grid defaults
|
||||||
|
SetGridVisibility( true );
|
||||||
|
SetGridStyle( GRID_STYLE_LINES );
|
||||||
|
SetGridOriginMarkerSize( 15 );
|
||||||
|
SetGridDrawThreshold( 10 );
|
||||||
|
SetCoarseGrid( 10 );
|
||||||
|
SetGridLineWidth( 0.5 );
|
||||||
|
|
||||||
|
// Initialize the cursor shape
|
||||||
|
SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
|
||||||
|
SetCursorSize( 80 );
|
||||||
|
SetCursorEnabled( false );
|
||||||
|
|
||||||
|
strokeFont.LoadNewStrokeFont( newstroke_font, newstroke_font_bufsize );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GAL::~GAL()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GAL::SetTextAttributes( const EDA_TEXT* aText )
|
||||||
|
{
|
||||||
|
strokeFont.SetGlyphSize( VECTOR2D( aText->GetSize() ) );
|
||||||
|
strokeFont.SetHorizontalJustify( aText->GetHorizJustify() );
|
||||||
|
strokeFont.SetVerticalJustify( aText->GetVertJustify() );
|
||||||
|
strokeFont.SetBold( aText->IsBold() );
|
||||||
|
strokeFont.SetItalic( aText->IsItalic() );
|
||||||
|
strokeFont.SetMirrored( aText->IsMirrored() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GAL::ComputeWorldScreenMatrix()
|
||||||
|
{
|
||||||
|
ComputeWorldScale();
|
||||||
|
|
||||||
|
worldScreenMatrix.SetIdentity();
|
||||||
|
|
||||||
|
MATRIX3x3D translation;
|
||||||
|
translation.SetIdentity();
|
||||||
|
translation.SetTranslation( 0.5 * screenSize );
|
||||||
|
|
||||||
|
MATRIX3x3D scale;
|
||||||
|
scale.SetIdentity();
|
||||||
|
scale.SetScale( VECTOR2D( worldScale, worldScale ) );
|
||||||
|
|
||||||
|
MATRIX3x3D flip;
|
||||||
|
flip.SetIdentity();
|
||||||
|
flip.SetScale( VECTOR2D( flipX, flipY ) );
|
||||||
|
|
||||||
|
MATRIX3x3D lookat;
|
||||||
|
lookat.SetIdentity();
|
||||||
|
lookat.SetTranslation( -lookAtPoint );
|
||||||
|
|
||||||
|
worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix;
|
||||||
|
screenWorldMatrix = worldScreenMatrix.Inverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GAL::DrawGrid()
|
||||||
|
{
|
||||||
|
if( !gridVisibility )
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetTarget( TARGET_NONCACHED );
|
||||||
|
|
||||||
|
// Draw the origin marker
|
||||||
|
double origSize = static_cast<double>( gridOriginMarkerSize ) / worldScale;
|
||||||
|
SetLayerDepth( GAL::GRID_DEPTH );
|
||||||
|
SetIsFill( false );
|
||||||
|
SetIsStroke( true );
|
||||||
|
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
|
||||||
|
SetLineWidth( gridLineWidth / worldScale );
|
||||||
|
DrawLine( gridOrigin + VECTOR2D( -origSize, -origSize ),
|
||||||
|
gridOrigin + VECTOR2D( origSize, origSize ) );
|
||||||
|
DrawLine( gridOrigin + VECTOR2D( -origSize, origSize ),
|
||||||
|
gridOrigin + VECTOR2D( origSize, -origSize ) );
|
||||||
|
DrawCircle( gridOrigin, origSize * 0.7 );
|
||||||
|
|
||||||
|
// Draw the grid
|
||||||
|
// For the drawing the start points, end points and increments have
|
||||||
|
// to be calculated in world coordinates
|
||||||
|
VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
|
||||||
|
VECTOR2D worldEndPoint = screenWorldMatrix * screenSize;
|
||||||
|
|
||||||
|
int gridScreenSizeDense = round( gridSize.x * worldScale );
|
||||||
|
int gridScreenSizeCoarse = round( gridSize.x * static_cast<double>( gridTick ) * worldScale );
|
||||||
|
|
||||||
|
// Compute the line marker or point radius of the grid
|
||||||
|
double marker = 2.0 * gridLineWidth / worldScale;
|
||||||
|
double doubleMarker = 2.0 * marker;
|
||||||
|
|
||||||
|
// Check if the grid would not be too dense
|
||||||
|
if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) > gridDrawThreshold )
|
||||||
|
{
|
||||||
|
// 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 );
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Draw the grid behind all other layers
|
||||||
|
SetLayerDepth( depthRange.y * 0.75 );
|
||||||
|
|
||||||
|
if( gridStyle == GRID_STYLE_LINES )
|
||||||
|
{
|
||||||
|
SetIsFill( false );
|
||||||
|
SetIsStroke( true );
|
||||||
|
SetStrokeColor( gridColor );
|
||||||
|
|
||||||
|
// 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( doubleMarker );
|
||||||
|
else
|
||||||
|
SetLineWidth( marker );
|
||||||
|
|
||||||
|
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( doubleMarker );
|
||||||
|
else
|
||||||
|
SetLineWidth( marker );
|
||||||
|
|
||||||
|
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold )
|
||||||
|
|| gridScreenSizeDense > gridDrawThreshold )
|
||||||
|
{
|
||||||
|
drawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ),
|
||||||
|
VECTOR2D( i * gridSize.x, gridEndY * gridSize.y ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Dotted grid
|
||||||
|
{
|
||||||
|
bool tickX, tickY;
|
||||||
|
SetIsFill( true );
|
||||||
|
SetIsStroke( false );
|
||||||
|
SetFillColor( gridColor );
|
||||||
|
|
||||||
|
for( int j = gridStartY; j < gridEndY; j += 1 )
|
||||||
|
{
|
||||||
|
if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold )
|
||||||
|
tickY = true;
|
||||||
|
else
|
||||||
|
tickY = false;
|
||||||
|
|
||||||
|
for( int i = gridStartX; i < gridEndX; i += 1 )
|
||||||
|
{
|
||||||
|
if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold )
|
||||||
|
tickX = true;
|
||||||
|
else
|
||||||
|
tickX = false;
|
||||||
|
|
||||||
|
if( tickX || tickY || gridScreenSizeDense > gridDrawThreshold )
|
||||||
|
{
|
||||||
|
double radius = ( tickX && tickY ) ? doubleMarker : marker;
|
||||||
|
DrawRectangle( VECTOR2D( i * gridSize.x - radius,
|
||||||
|
j * gridSize.y - radius ),
|
||||||
|
VECTOR2D( i * gridSize.x + radius,
|
||||||
|
j * gridSize.y + radius ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VECTOR2D GAL::GetGridPoint( VECTOR2D aPoint ) const
|
||||||
|
{
|
||||||
|
VECTOR2D pointWorld = ToWorld( aPoint );
|
||||||
|
|
||||||
|
pointWorld.x = round( pointWorld.x / gridSize.x ) * gridSize.x;
|
||||||
|
pointWorld.y = round( pointWorld.y / gridSize.y ) * gridSize.y;
|
||||||
|
|
||||||
|
return ToScreen( pointWorld );
|
||||||
|
}
|
|
@ -0,0 +1,550 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file cached_container.cpp
|
||||||
|
* @brief Class to store instances of VERTEX with caching. It allows storing VERTEX objects and
|
||||||
|
* associates them with VERTEX_ITEMs. This leads to a possibility of caching vertices data in the
|
||||||
|
* GPU memory and a fast reuse of that data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/cached_container.h>
|
||||||
|
#include <gal/opengl/vertex_manager.h>
|
||||||
|
#include <gal/opengl/vertex_item.h>
|
||||||
|
#include <gal/opengl/shader.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <list>
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
#include <profile.h>
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
|
||||||
|
VERTEX_CONTAINER( aSize ), m_item( NULL )
|
||||||
|
{
|
||||||
|
// In the beginning there is only free space
|
||||||
|
m_freeChunks.insert( CHUNK( aSize, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||||
|
{
|
||||||
|
wxASSERT( aItem != NULL );
|
||||||
|
|
||||||
|
m_item = aItem;
|
||||||
|
m_itemSize = m_item->GetSize();
|
||||||
|
m_chunkSize = m_itemSize;
|
||||||
|
|
||||||
|
if( m_itemSize == 0 )
|
||||||
|
m_items.insert( m_item ); // The item was not stored before
|
||||||
|
else
|
||||||
|
m_chunkOffset = m_item->GetOffset();
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 1
|
||||||
|
wxLogDebug( wxT( "Adding/editing item 0x%08lx (size %d)" ), (long) m_item, m_itemSize );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::FinishItem()
|
||||||
|
{
|
||||||
|
wxASSERT( m_item != NULL );
|
||||||
|
wxASSERT( m_item->GetSize() == m_itemSize );
|
||||||
|
|
||||||
|
// Finishing the previously edited item
|
||||||
|
if( m_itemSize < m_chunkSize )
|
||||||
|
{
|
||||||
|
// There is some not used but reserved memory left, so we should return it to the pool
|
||||||
|
int itemOffset = m_item->GetOffset();
|
||||||
|
|
||||||
|
// Add the not used memory back to the pool
|
||||||
|
m_freeChunks.insert( CHUNK( m_chunkSize - m_itemSize, itemOffset + m_itemSize ) );
|
||||||
|
m_freeSpace += ( m_chunkSize - m_itemSize );
|
||||||
|
// mergeFreeChunks(); // veery slow and buggy
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 1
|
||||||
|
wxLogDebug( wxT( "Finishing item 0x%08lx (size %d)" ), (long) m_item, m_itemSize );
|
||||||
|
test();
|
||||||
|
m_item = NULL; // electric fence
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||||
|
{
|
||||||
|
wxASSERT( m_item != NULL );
|
||||||
|
|
||||||
|
if( m_failed )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( m_itemSize + aSize > m_chunkSize )
|
||||||
|
{
|
||||||
|
// There is not enough space in the currently reserved chunk, so we have to resize it
|
||||||
|
|
||||||
|
// Reserve a bigger memory chunk for the current item and
|
||||||
|
// make it multiple of 3 to store triangles
|
||||||
|
m_chunkSize = ( 2 * m_itemSize ) + aSize + ( 3 - aSize % 3 );
|
||||||
|
// Save the current size before reallocating
|
||||||
|
m_chunkOffset = reallocate( m_chunkSize );
|
||||||
|
|
||||||
|
if( m_chunkOffset > m_currentSize )
|
||||||
|
{
|
||||||
|
m_failed = true;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VERTEX* reserved = &m_vertices[m_chunkOffset + m_itemSize];
|
||||||
|
m_itemSize += aSize;
|
||||||
|
// Now the item officially possesses the memory chunk
|
||||||
|
m_item->setSize( m_itemSize );
|
||||||
|
|
||||||
|
// The content has to be updated
|
||||||
|
m_dirty = true;
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 1
|
||||||
|
test();
|
||||||
|
#endif
|
||||||
|
#if CACHED_CONTAINER_TEST > 2
|
||||||
|
showFreeChunks();
|
||||||
|
showReservedChunks();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return reserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
|
||||||
|
{
|
||||||
|
wxASSERT( aItem != NULL );
|
||||||
|
wxASSERT( m_items.find( aItem ) != m_items.end() );
|
||||||
|
|
||||||
|
int size = aItem->GetSize();
|
||||||
|
int offset = aItem->GetOffset();
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 1
|
||||||
|
wxLogDebug( wxT( "Removing 0x%08lx (size %d offset %d)" ), (long) aItem, size, offset );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Insert a free memory chunk entry in the place where item was stored
|
||||||
|
if( size > 0 )
|
||||||
|
{
|
||||||
|
m_freeChunks.insert( CHUNK( size, offset ) );
|
||||||
|
m_freeSpace += size;
|
||||||
|
// Indicate that the item is not stored in the container anymore
|
||||||
|
aItem->setSize( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_items.erase( aItem );
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 1
|
||||||
|
test();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Dynamic memory freeing, there is no point in holding
|
||||||
|
// a large amount of memory when there is no use for it
|
||||||
|
if( m_freeSpace > ( m_currentSize / 2 ) && m_currentSize > m_initialSize )
|
||||||
|
{
|
||||||
|
resizeContainer( m_currentSize / 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::Clear()
|
||||||
|
{
|
||||||
|
// Change size to the default one
|
||||||
|
m_vertices = static_cast<VERTEX*>( realloc( m_vertices,
|
||||||
|
m_initialSize * sizeof( VERTEX ) ) );
|
||||||
|
|
||||||
|
// Reset state variables
|
||||||
|
m_freeSpace = m_initialSize;
|
||||||
|
m_currentSize = m_initialSize;
|
||||||
|
m_failed = false;
|
||||||
|
|
||||||
|
// Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
|
||||||
|
// in the container anymore
|
||||||
|
ITEMS::iterator it;
|
||||||
|
|
||||||
|
for( it = m_items.begin(); it != m_items.end(); ++it )
|
||||||
|
{
|
||||||
|
( *it )->setSize( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_items.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// Now there is only free space left
|
||||||
|
m_freeChunks.clear();
|
||||||
|
m_freeChunks.insert( CHUNK( m_freeSpace, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX* CACHED_CONTAINER::GetVertices( const VERTEX_ITEM* aItem ) const
|
||||||
|
{
|
||||||
|
int offset = aItem->GetOffset();
|
||||||
|
|
||||||
|
return &m_vertices[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
|
||||||
|
{
|
||||||
|
wxASSERT( aSize > 0 );
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 2
|
||||||
|
wxLogDebug( wxT( "Resize 0x%08lx from %d to %d" ), (long) m_item, m_itemSize, aSize );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Is there enough space to store vertices?
|
||||||
|
if( m_freeSpace < aSize )
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
// Would it be enough to double the current space?
|
||||||
|
if( aSize < m_freeSpace + m_currentSize )
|
||||||
|
{
|
||||||
|
// Yes: exponential growing
|
||||||
|
result = resizeContainer( m_currentSize * 2 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No: grow to the nearest bigger power of 2
|
||||||
|
result = resizeContainer( getPowerOf2( m_currentSize * 2 + aSize ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !result )
|
||||||
|
return UINT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the free space chunk of at least given size
|
||||||
|
FREE_CHUNK_MAP::iterator newChunk = m_freeChunks.lower_bound( aSize );
|
||||||
|
|
||||||
|
if( newChunk == m_freeChunks.end() )
|
||||||
|
{
|
||||||
|
// In the case when there is enough space to store the vertices,
|
||||||
|
// but the free space is not continous we should defragment the container
|
||||||
|
if( !defragment() )
|
||||||
|
return UINT_MAX;
|
||||||
|
|
||||||
|
// Update the current offset
|
||||||
|
m_chunkOffset = m_item->GetOffset();
|
||||||
|
|
||||||
|
// We can take the first free chunk, as there is only one after defragmentation
|
||||||
|
// and we can be sure that it provides enough space to store the object
|
||||||
|
newChunk = m_freeChunks.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters of the allocated cuhnk
|
||||||
|
unsigned int chunkSize = newChunk->first;
|
||||||
|
unsigned int chunkOffset = newChunk->second;
|
||||||
|
|
||||||
|
wxASSERT( chunkSize >= aSize );
|
||||||
|
wxASSERT( chunkOffset < m_currentSize );
|
||||||
|
|
||||||
|
// Check if the item was previously stored in the container
|
||||||
|
if( m_itemSize > 0 )
|
||||||
|
{
|
||||||
|
#if CACHED_CONTAINER_TEST > 3
|
||||||
|
wxLogDebug( wxT( "Moving 0x%08x from 0x%08x to 0x%08x" ),
|
||||||
|
(int) m_item, oldChunkOffset, chunkOffset );
|
||||||
|
#endif
|
||||||
|
// The item was reallocated, so we have to copy all the old data to the new place
|
||||||
|
memcpy( &m_vertices[chunkOffset], &m_vertices[m_chunkOffset],
|
||||||
|
m_itemSize * VertexSize );
|
||||||
|
|
||||||
|
// Free the space previously used by the chunk
|
||||||
|
wxASSERT( m_itemSize > 0 );
|
||||||
|
m_freeChunks.insert( CHUNK( m_itemSize, m_chunkOffset ) );
|
||||||
|
m_freeSpace += m_itemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the allocated chunk from the free space pool
|
||||||
|
m_freeChunks.erase( newChunk );
|
||||||
|
|
||||||
|
// If there is some space left, return it to the pool - add an entry for it
|
||||||
|
if( chunkSize > aSize )
|
||||||
|
{
|
||||||
|
m_freeChunks.insert( CHUNK( chunkSize - aSize, chunkOffset + aSize ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freeSpace -= aSize;
|
||||||
|
// mergeFreeChunks(); // veery slow and buggy
|
||||||
|
|
||||||
|
m_item->setOffset( chunkOffset );
|
||||||
|
|
||||||
|
return chunkOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CACHED_CONTAINER::defragment( VERTEX* aTarget )
|
||||||
|
{
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
wxLogDebug( wxT( "Defragmenting" ) );
|
||||||
|
|
||||||
|
prof_counter totalTime;
|
||||||
|
prof_start( &totalTime, false );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( aTarget == NULL )
|
||||||
|
{
|
||||||
|
// No target was specified, so we have to reallocate our own space
|
||||||
|
aTarget = static_cast<VERTEX*>( malloc( m_currentSize * sizeof( VERTEX ) ) );
|
||||||
|
|
||||||
|
if( aTarget == NULL )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Run out of memory" ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int newOffset = 0;
|
||||||
|
ITEMS::iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||||
|
{
|
||||||
|
VERTEX_ITEM* item = *it;
|
||||||
|
int itemOffset = item->GetOffset();
|
||||||
|
int itemSize = item->GetSize();
|
||||||
|
|
||||||
|
// Move an item to the new container
|
||||||
|
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );
|
||||||
|
|
||||||
|
// Update new offset
|
||||||
|
item->setOffset( newOffset );
|
||||||
|
|
||||||
|
// Move to the next free space
|
||||||
|
newOffset += itemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
free( m_vertices );
|
||||||
|
m_vertices = aTarget;
|
||||||
|
|
||||||
|
// Now there is only one big chunk of free memory
|
||||||
|
m_freeChunks.clear();
|
||||||
|
wxASSERT( m_freeSpace > 0 );
|
||||||
|
m_freeChunks.insert( CHUNK( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
prof_end( &totalTime );
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "Defragmented the container storing %d vertices / %.1f ms" ),
|
||||||
|
m_currentSize - m_freeSpace, (double) totalTime.value / 1000.0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::mergeFreeChunks()
|
||||||
|
{
|
||||||
|
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
prof_counter totalTime;
|
||||||
|
prof_start( &totalTime, false );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Reversed free chunks map - this one stores chunk size with its offset as the key
|
||||||
|
std::list<CHUNK> freeChunks;
|
||||||
|
|
||||||
|
FREE_CHUNK_MAP::const_iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_freeChunks.begin(), it_end = m_freeChunks.end(); it != it_end; ++it )
|
||||||
|
{
|
||||||
|
freeChunks.push_back( std::make_pair( it->second, it->first ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freeChunks.clear();
|
||||||
|
freeChunks.sort();
|
||||||
|
|
||||||
|
std::list<CHUNK>::const_iterator itf, itf_end;
|
||||||
|
unsigned int offset = freeChunks.front().first;
|
||||||
|
unsigned int size = freeChunks.front().second;
|
||||||
|
freeChunks.pop_front();
|
||||||
|
|
||||||
|
for( itf = freeChunks.begin(), itf_end = freeChunks.end(); itf != itf_end; ++itf )
|
||||||
|
{
|
||||||
|
if( itf->first == offset + size )
|
||||||
|
{
|
||||||
|
// These chunks can be merged, so just increase the current chunk size and go on
|
||||||
|
size += itf->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// These chunks cannot be merged
|
||||||
|
// So store the previous one
|
||||||
|
m_freeChunks.insert( std::make_pair( size, offset ) );
|
||||||
|
// and let's check the next chunk
|
||||||
|
offset = itf->first;
|
||||||
|
size = itf->second;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the last one
|
||||||
|
m_freeChunks.insert( std::make_pair( size, offset ) );
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
prof_end( &totalTime );
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CACHED_CONTAINER::resizeContainer( unsigned int aNewSize )
|
||||||
|
{
|
||||||
|
wxASSERT( aNewSize != m_currentSize );
|
||||||
|
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
wxLogDebug( wxT( "Resizing container from %d to %d" ), m_currentSize, aNewSize );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VERTEX* newContainer;
|
||||||
|
|
||||||
|
if( aNewSize < m_currentSize )
|
||||||
|
{
|
||||||
|
// Shrinking container
|
||||||
|
// Sanity check, no shrinking if we cannot fit all the data
|
||||||
|
if( reservedSpace() > aNewSize )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newContainer = static_cast<VERTEX*>( malloc( aNewSize * sizeof( VERTEX ) ) );
|
||||||
|
|
||||||
|
if( newContainer == NULL )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Run out of memory" ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defragment directly to the new, smaller container
|
||||||
|
defragment( newContainer );
|
||||||
|
|
||||||
|
// We have to correct freeChunks after defragmentation
|
||||||
|
m_freeChunks.clear();
|
||||||
|
wxASSERT( aNewSize - reservedSpace() > 0 );
|
||||||
|
m_freeChunks.insert( CHUNK( aNewSize - reservedSpace(), reservedSpace() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Enlarging container
|
||||||
|
newContainer = static_cast<VERTEX*>( realloc( m_vertices, aNewSize * sizeof( VERTEX ) ) );
|
||||||
|
|
||||||
|
if( newContainer == NULL )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Run out of memory" ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an entry for the new memory chunk at the end of the container
|
||||||
|
m_freeChunks.insert( CHUNK( aNewSize - m_currentSize, m_currentSize ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vertices = newContainer;
|
||||||
|
|
||||||
|
m_freeSpace += ( aNewSize - m_currentSize );
|
||||||
|
m_currentSize = aNewSize;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int CACHED_CONTAINER::getPowerOf2( unsigned int aNumber ) const
|
||||||
|
{
|
||||||
|
unsigned int power = 1;
|
||||||
|
|
||||||
|
while( power < aNumber && power != 0 )
|
||||||
|
power <<= 1;
|
||||||
|
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CACHED_CONTAINER_TEST
|
||||||
|
void CACHED_CONTAINER::showFreeChunks()
|
||||||
|
{
|
||||||
|
FreeChunkMap::iterator it;
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "Free chunks:" ) );
|
||||||
|
|
||||||
|
for( it = m_freeChunks.begin(); it != m_freeChunks.end(); ++it )
|
||||||
|
{
|
||||||
|
unsigned int offset = getChunkOffset( *it );
|
||||||
|
unsigned int size = getChunkSize( *it );
|
||||||
|
wxASSERT( size > 0 );
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "[0x%08x-0x%08x] (size %d)" ),
|
||||||
|
offset, offset + size - 1, size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::showReservedChunks()
|
||||||
|
{
|
||||||
|
Items::iterator it;
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "Reserved chunks:" ) );
|
||||||
|
|
||||||
|
for( it = m_items.begin(); it != m_items.end(); ++it )
|
||||||
|
{
|
||||||
|
VERTEX_ITEM* item = *it;
|
||||||
|
unsigned int offset = item->GetOffset();
|
||||||
|
unsigned int size = item->GetSize();
|
||||||
|
wxASSERT( size > 0 );
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "[0x%08x-0x%08x] @ 0x%08lx (size %d)" ),
|
||||||
|
offset, offset + size - 1, (long) item, size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CACHED_CONTAINER::test()
|
||||||
|
{
|
||||||
|
// Free space check
|
||||||
|
unsigned int freeSpace = 0;
|
||||||
|
FreeChunkMap::iterator itf;
|
||||||
|
|
||||||
|
for( itf = m_freeChunks.begin(); itf != m_freeChunks.end(); ++itf )
|
||||||
|
freeSpace += getChunkSize( *itf );
|
||||||
|
|
||||||
|
wxASSERT( freeSpace == m_freeSpace );
|
||||||
|
|
||||||
|
// Reserved space check
|
||||||
|
/*unsigned int reservedSpace = 0;
|
||||||
|
Items::iterator itr;
|
||||||
|
for( itr = m_items.begin(); itr != m_items.end(); ++itr )
|
||||||
|
reservedSpace += ( *itr )->GetSize();
|
||||||
|
reservedSpace += m_itemSize; // Add the current chunk size
|
||||||
|
|
||||||
|
wxASSERT( ( freeSpace + reservedSpace ) == m_currentSize );*/
|
||||||
|
|
||||||
|
// Overlapping check TBD
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CACHED_CONTAINER_TEST */
|
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file gpu_manager.cpp
|
||||||
|
* @brief Class to handle uploading vertices and indices to GPU in drawing purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/gpu_manager.h>
|
||||||
|
#include <gal/opengl/cached_container.h>
|
||||||
|
#include <gal/opengl/noncached_container.h>
|
||||||
|
#include <gal/opengl/shader.h>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <wx/log.h>
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
#include <profile.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
|
||||||
|
{
|
||||||
|
if( typeid( *aContainer ) == typeid( CACHED_CONTAINER ) )
|
||||||
|
return new GPU_CACHED_MANAGER( aContainer );
|
||||||
|
else if( typeid( *aContainer ) == typeid( NONCACHED_CONTAINER ) )
|
||||||
|
return new GPU_NONCACHED_MANAGER( aContainer );
|
||||||
|
|
||||||
|
wxASSERT_MSG( false, "Not handled container type" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||||
|
m_isDrawing( false ), m_container( aContainer ), m_shader( NULL )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GPU_MANAGER::~GPU_MANAGER()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_MANAGER::SetShader( SHADER& aShader )
|
||||||
|
{
|
||||||
|
m_shader = &aShader;
|
||||||
|
|
||||||
|
m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
|
||||||
|
|
||||||
|
if( m_shaderAttrib == -1 )
|
||||||
|
{
|
||||||
|
wxLogFatalError( wxT( "Could not get the shader attribute location" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cached manager
|
||||||
|
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||||
|
GPU_MANAGER( aContainer ), m_buffersInitialized( false ),
|
||||||
|
m_indicesSize( 0 )
|
||||||
|
{
|
||||||
|
// Allocate the biggest possible buffer for indices
|
||||||
|
m_indices.reset( new GLuint[aContainer->GetSize()] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
|
||||||
|
{
|
||||||
|
if( m_buffersInitialized )
|
||||||
|
{
|
||||||
|
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||||
|
glDeleteBuffers( 1, &m_verticesBuffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::Initialize()
|
||||||
|
{
|
||||||
|
wxASSERT( !m_buffersInitialized );
|
||||||
|
|
||||||
|
if( !m_buffersInitialized )
|
||||||
|
{
|
||||||
|
glGenBuffers( 1, &m_verticesBuffer );
|
||||||
|
m_buffersInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::BeginDrawing()
|
||||||
|
{
|
||||||
|
wxASSERT( !m_isDrawing );
|
||||||
|
|
||||||
|
if( m_container->IsDirty() )
|
||||||
|
uploadToGpu();
|
||||||
|
|
||||||
|
// Number of vertices to be drawn in the EndDrawing()
|
||||||
|
m_indicesSize = 0;
|
||||||
|
// Set the indices pointer to the beginning of the indices-to-draw buffer
|
||||||
|
m_indicesPtr = m_indices.get();
|
||||||
|
|
||||||
|
m_isDrawing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
|
||||||
|
{
|
||||||
|
wxASSERT( m_isDrawing );
|
||||||
|
|
||||||
|
// Copy indices of items that should be drawn to GPU memory
|
||||||
|
for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ );
|
||||||
|
|
||||||
|
m_indicesSize += aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::DrawAll()
|
||||||
|
{
|
||||||
|
wxASSERT( m_isDrawing );
|
||||||
|
|
||||||
|
m_indicesSize = m_container->GetSize();
|
||||||
|
for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::EndDrawing()
|
||||||
|
{
|
||||||
|
wxASSERT( m_isDrawing );
|
||||||
|
|
||||||
|
// Prepare buffers
|
||||||
|
glEnableClientState( GL_VERTEX_ARRAY );
|
||||||
|
glEnableClientState( GL_COLOR_ARRAY );
|
||||||
|
|
||||||
|
// Bind vertices data buffers
|
||||||
|
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
|
||||||
|
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 );
|
||||||
|
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset );
|
||||||
|
|
||||||
|
if( m_shader != NULL ) // Use shader if applicable
|
||||||
|
{
|
||||||
|
m_shader->Use();
|
||||||
|
glEnableVertexAttribArray( m_shaderAttrib );
|
||||||
|
glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
|
||||||
|
VertexSize, (GLvoid*) ShaderOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, (GLvoid*) m_indices.get() );
|
||||||
|
|
||||||
|
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||||
|
|
||||||
|
// Deactivate vertex array
|
||||||
|
glDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
glDisableClientState( GL_VERTEX_ARRAY );
|
||||||
|
|
||||||
|
if( m_shader != NULL )
|
||||||
|
{
|
||||||
|
glDisableVertexAttribArray( m_shaderAttrib );
|
||||||
|
m_shader->Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isDrawing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_CACHED_MANAGER::uploadToGpu()
|
||||||
|
{
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
prof_counter totalTime;
|
||||||
|
prof_start( &totalTime, false );
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
|
||||||
|
if( !m_buffersInitialized )
|
||||||
|
Initialize();
|
||||||
|
|
||||||
|
int bufferSize = m_container->GetSize();
|
||||||
|
GLfloat* vertices = (GLfloat*) m_container->GetAllVertices();
|
||||||
|
|
||||||
|
// Upload vertices coordinates and shader types to GPU memory
|
||||||
|
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
|
||||||
|
glBufferData( GL_ARRAY_BUFFER, bufferSize * VertexSize, vertices, GL_DYNAMIC_DRAW );
|
||||||
|
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||||
|
|
||||||
|
// Allocate the biggest possible buffer for indices
|
||||||
|
m_indices.reset( new GLuint[bufferSize] );
|
||||||
|
|
||||||
|
if( glGetError() != GL_NO_ERROR )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Error during data upload to the GPU memory" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
prof_end( &totalTime );
|
||||||
|
|
||||||
|
wxLogDebug( wxT( "Uploading %d vertices to GPU / %.1f ms" ),
|
||||||
|
bufferSize, (double) totalTime.value / 1000.0 );
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Noncached manager
|
||||||
|
GPU_NONCACHED_MANAGER::GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||||
|
GPU_MANAGER( aContainer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_NONCACHED_MANAGER::Initialize()
|
||||||
|
{
|
||||||
|
// Nothing has to be intialized
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_NONCACHED_MANAGER::BeginDrawing()
|
||||||
|
{
|
||||||
|
// Nothing has to be prepared
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_NONCACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_NONCACHED_MANAGER::DrawAll()
|
||||||
|
{
|
||||||
|
// This is the default use case, nothing has to be done
|
||||||
|
// The real rendering takes place in the EndDrawing() function
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_NONCACHED_MANAGER::EndDrawing()
|
||||||
|
{
|
||||||
|
VERTEX* vertices = m_container->GetAllVertices();
|
||||||
|
GLfloat* coordinates = (GLfloat*) ( vertices );
|
||||||
|
GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset;
|
||||||
|
|
||||||
|
// Prepare buffers
|
||||||
|
glEnableClientState( GL_VERTEX_ARRAY );
|
||||||
|
glEnableClientState( GL_COLOR_ARRAY );
|
||||||
|
|
||||||
|
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, coordinates );
|
||||||
|
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, colors );
|
||||||
|
|
||||||
|
if( m_shader != NULL ) // Use shader if applicable
|
||||||
|
{
|
||||||
|
GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat);
|
||||||
|
|
||||||
|
m_shader->Use();
|
||||||
|
glEnableVertexAttribArray( m_shaderAttrib );
|
||||||
|
glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
|
||||||
|
VertexSize, shaders );
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
|
||||||
|
|
||||||
|
// Deactivate vertex array
|
||||||
|
glDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
glDisableClientState( GL_VERTEX_ARRAY );
|
||||||
|
|
||||||
|
if( m_shader != NULL )
|
||||||
|
{
|
||||||
|
glDisableVertexAttribArray( m_shaderAttrib );
|
||||||
|
m_shader->Deactivate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file noncached_container.cpp
|
||||||
|
* @brief Class to store instances of VERTEX without caching. It allows a fast one-frame drawing
|
||||||
|
* and then clearing the buffer and starting from scratch.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/noncached_container.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
|
||||||
|
VERTEX_CONTAINER( aSize ), m_freePtr( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NONCACHED_CONTAINER::~NONCACHED_CONTAINER()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NONCACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||||
|
{
|
||||||
|
// Nothing has to be done, as the noncached container
|
||||||
|
// does not care about VERTEX_ITEMs ownership
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX* NONCACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||||
|
{
|
||||||
|
if( m_freeSpace < aSize )
|
||||||
|
{
|
||||||
|
// Double the space
|
||||||
|
VERTEX* newVertices = static_cast<VERTEX*>( realloc( m_vertices,
|
||||||
|
m_currentSize * 2 *
|
||||||
|
sizeof(VERTEX) ) );
|
||||||
|
|
||||||
|
if( newVertices != NULL )
|
||||||
|
{
|
||||||
|
m_vertices = newVertices;
|
||||||
|
m_freeSpace += m_currentSize;
|
||||||
|
m_currentSize *= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VERTEX* freeVertex = &m_vertices[m_freePtr];
|
||||||
|
|
||||||
|
// Move to the next free chunk
|
||||||
|
m_freePtr += aSize;
|
||||||
|
m_freeSpace -= aSize;
|
||||||
|
|
||||||
|
return freeVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NONCACHED_CONTAINER::Clear()
|
||||||
|
{
|
||||||
|
m_freePtr = 0;
|
||||||
|
m_freeSpace = m_currentSize;
|
||||||
|
}
|
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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:O//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 opengl_compositor.cpp
|
||||||
|
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
|
||||||
|
* later compositing into a single image (OpenGL flavour).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/opengl_compositor.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() :
|
||||||
|
m_initialized( false ), m_current( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OPENGL_COMPOSITOR::~OPENGL_COMPOSITOR()
|
||||||
|
{
|
||||||
|
if( m_initialized )
|
||||||
|
clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::Initialize()
|
||||||
|
{
|
||||||
|
if( m_initialized )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the maximum number of buffers
|
||||||
|
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &m_maxBuffers );
|
||||||
|
|
||||||
|
// We need framebuffer objects for drawing the screen contents
|
||||||
|
// Generate framebuffer and a depth buffer
|
||||||
|
glGenFramebuffersEXT( 1, &m_framebuffer );
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER, m_framebuffer );
|
||||||
|
m_currentFbo = m_framebuffer;
|
||||||
|
|
||||||
|
// Allocate memory for the depth buffer
|
||||||
|
// Attach the depth buffer to the framebuffer
|
||||||
|
glGenRenderbuffersEXT( 1, &m_depthBuffer );
|
||||||
|
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||||
|
|
||||||
|
// Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer
|
||||||
|
// this is required later for anti-aliasing
|
||||||
|
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL, m_width, m_height );
|
||||||
|
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT,
|
||||||
|
GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||||
|
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT,
|
||||||
|
GL_RENDERBUFFER_EXT, m_depthBuffer );
|
||||||
|
|
||||||
|
// Unbind the framebuffer, so by default all the rendering goes directly to the display
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING );
|
||||||
|
m_currentFbo = 0;
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
|
||||||
|
{
|
||||||
|
if( m_initialized )
|
||||||
|
clean();
|
||||||
|
|
||||||
|
m_width = aWidth;
|
||||||
|
m_height = aHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int OPENGL_COMPOSITOR::CreateBuffer()
|
||||||
|
{
|
||||||
|
wxASSERT( m_initialized );
|
||||||
|
|
||||||
|
if( usedBuffers() >= m_maxBuffers )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Cannot create more framebuffers. OpenGL rendering backend requires at"
|
||||||
|
"least 3 framebuffers. You may try to update/change "
|
||||||
|
"your graphic drivers." ) );
|
||||||
|
return 0; // Unfortunately we have no more free buffers left
|
||||||
|
}
|
||||||
|
|
||||||
|
// GL_COLOR_ATTACHMENTn are consecutive integers
|
||||||
|
GLuint attachmentPoint = GL_COLOR_ATTACHMENT0 + usedBuffers();
|
||||||
|
GLuint textureTarget;
|
||||||
|
|
||||||
|
// Generate the texture for the pixel storage
|
||||||
|
glGenTextures( 1, &textureTarget );
|
||||||
|
glBindTexture( GL_TEXTURE_2D, textureTarget );
|
||||||
|
|
||||||
|
// Set texture parameters
|
||||||
|
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||||
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, NULL );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||||
|
|
||||||
|
// Bind the texture to the specific attachment point, clear and rebind the screen
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer );
|
||||||
|
m_currentFbo = m_framebuffer;
|
||||||
|
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 );
|
||||||
|
|
||||||
|
// Check the status, exit if the framebuffer can't be created
|
||||||
|
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
|
||||||
|
|
||||||
|
if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
|
||||||
|
{
|
||||||
|
switch( status )
|
||||||
|
{
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||||
|
wxLogFatalError( wxT( "Cannot create the framebuffer." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||||
|
wxLogFatalError( wxT( "The framebuffer attachment points are incomplete." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||||
|
wxLogFatalError( wxT( "The framebuffer does not have at least "
|
||||||
|
"one image attached to it." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||||
|
wxLogFatalError( wxT( "The framebuffer read buffer is incomplete." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||||
|
wxLogFatalError( wxT( "The combination of internal formats of the attached images "
|
||||||
|
"violates an implementation-dependent set of restrictions." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
|
||||||
|
wxLogFatalError( wxT( "GL_RENDERBUFFER_SAMPLES is not the same "
|
||||||
|
"for all attached renderbuffers" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
|
||||||
|
wxLogFatalError( wxT( "Framebuffer incomplete layer targets errors." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxLogFatalError( wxT( "Cannot create the framebuffer." ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearBuffer();
|
||||||
|
|
||||||
|
// Return to direct rendering (we were asked only to create a buffer, not switch to one)
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING );
|
||||||
|
m_currentFbo = DIRECT_RENDERING;
|
||||||
|
|
||||||
|
// Store the new buffer
|
||||||
|
OPENGL_BUFFER buffer = { textureTarget, attachmentPoint };
|
||||||
|
m_buffers.push_back( buffer );
|
||||||
|
|
||||||
|
return usedBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
|
||||||
|
{
|
||||||
|
if( aBufferHandle > usedBuffers() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Change the rendering destination to the selected attachment point
|
||||||
|
if( aBufferHandle == DIRECT_RENDERING )
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING );
|
||||||
|
m_currentFbo = DIRECT_RENDERING;
|
||||||
|
}
|
||||||
|
else if( m_currentFbo != m_framebuffer )
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer );
|
||||||
|
m_currentFbo = m_framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_currentFbo != DIRECT_RENDERING )
|
||||||
|
{
|
||||||
|
m_current = aBufferHandle - 1;
|
||||||
|
glDrawBuffer( m_buffers[m_current].attachmentPoint );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::ClearBuffer()
|
||||||
|
{
|
||||||
|
wxASSERT( m_initialized );
|
||||||
|
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
|
||||||
|
{
|
||||||
|
wxASSERT( m_initialized );
|
||||||
|
|
||||||
|
if( aBufferHandle == 0 || aBufferHandle > usedBuffers() )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Wrong framebuffer handle" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to the main framebuffer and blit the scene
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING );
|
||||||
|
m_currentFbo = DIRECT_RENDERING;
|
||||||
|
|
||||||
|
// Depth test has to be disabled to make transparency working
|
||||||
|
glDisable( GL_DEPTH_TEST );
|
||||||
|
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
|
||||||
|
|
||||||
|
// Enable texturing and bind the main texture
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glBindTexture( GL_TEXTURE_2D, m_buffers[aBufferHandle - 1].textureTarget );
|
||||||
|
|
||||||
|
// Draw a full screen quad with the texture
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glBegin( GL_TRIANGLES );
|
||||||
|
glTexCoord2f( 0.0f, 1.0f );
|
||||||
|
glVertex2f( -1.0f, -1.0f );
|
||||||
|
glTexCoord2f( 1.0f, 1.0f );
|
||||||
|
glVertex2f( 1.0f, -1.0f );
|
||||||
|
glTexCoord2f( 1.0f, 0.0f );
|
||||||
|
glVertex2f( 1.0f, 1.0f );
|
||||||
|
|
||||||
|
glTexCoord2f( 0.0f, 1.0f );
|
||||||
|
glVertex2f( -1.0f, -1.0f );
|
||||||
|
glTexCoord2f( 1.0f, 0.0f );
|
||||||
|
glVertex2f( 1.0f, 1.0f );
|
||||||
|
glTexCoord2f( 0.0f, 0.0f );
|
||||||
|
glVertex2f( -1.0f, 1.0f );
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_COMPOSITOR::clean()
|
||||||
|
{
|
||||||
|
wxASSERT( m_initialized );
|
||||||
|
|
||||||
|
glDeleteFramebuffersEXT( 1, &m_framebuffer );
|
||||||
|
glDeleteRenderbuffersEXT( 1, &m_depthBuffer );
|
||||||
|
|
||||||
|
OPENGL_BUFFERS::const_iterator it;
|
||||||
|
|
||||||
|
for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
|
||||||
|
{
|
||||||
|
glDeleteTextures( 1, &it->textureTarget );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffers.clear();
|
||||||
|
|
||||||
|
m_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint OPENGL_COMPOSITOR::m_currentFbo = DIRECT_RENDERING;
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
#include "shader_src.h"
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
SHADER::SHADER() :
|
||||||
|
isProgramCreated( false ),
|
||||||
|
isShaderLinked( false ),
|
||||||
|
active( 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHADER::LoadBuiltinShader( unsigned int aShaderNumber, SHADER_TYPE aShaderType )
|
||||||
|
{
|
||||||
|
if( aShaderNumber >= shaders_number )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return addSource( std::string( shaders_src[aShaderNumber] ), aShaderType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHADER::LoadShaderFromFile( const std::string& aShaderSourceName, SHADER_TYPE aShaderType )
|
||||||
|
{
|
||||||
|
// Load shader sources
|
||||||
|
const std::string shaderSource = readSource( aShaderSourceName );
|
||||||
|
|
||||||
|
return addSource( shaderSource, aShaderType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHADER::ConfigureGeometryShader( GLuint maxVertices, GLuint geometryInputType,
|
||||||
|
GLuint geometryOutputType )
|
||||||
|
{
|
||||||
|
maximumVertices = maxVertices;
|
||||||
|
geomInputType = geometryInputType;
|
||||||
|
geomOutputType = geometryOutputType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHADER::Link()
|
||||||
|
{
|
||||||
|
// Shader linking
|
||||||
|
glLinkProgram( programNumber );
|
||||||
|
programInfo( programNumber );
|
||||||
|
|
||||||
|
// Check the Link state
|
||||||
|
glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB,
|
||||||
|
(GLint*) &isShaderLinked );
|
||||||
|
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
|
||||||
|
if( !isShaderLinked )
|
||||||
|
{
|
||||||
|
int maxLength;
|
||||||
|
glGetProgramiv( programNumber, GL_INFO_LOG_LENGTH, &maxLength );
|
||||||
|
maxLength = maxLength + 1;
|
||||||
|
char* linkInfoLog = new char[maxLength];
|
||||||
|
glGetProgramInfoLog( programNumber, maxLength, &maxLength, linkInfoLog );
|
||||||
|
std::cerr << "Shader linking error:" << std::endl;
|
||||||
|
std::cerr << linkInfoLog;
|
||||||
|
delete[] linkInfoLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __WXDEBUG__ */
|
||||||
|
|
||||||
|
return isShaderLinked;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHADER::AddParameter( const std::string& aParameterName )
|
||||||
|
{
|
||||||
|
GLint location = glGetUniformLocation( programNumber, aParameterName.c_str() );
|
||||||
|
|
||||||
|
if( location != -1 )
|
||||||
|
{
|
||||||
|
parameterLocation.push_back( location );
|
||||||
|
}
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHADER::SetParameter( int parameterNumber, float value ) const
|
||||||
|
{
|
||||||
|
glUniform1f( parameterLocation[parameterNumber], value );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHADER::SetParameter( int parameterNumber, int value ) const
|
||||||
|
{
|
||||||
|
glUniform1i( parameterLocation[parameterNumber], value );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHADER::GetAttribute( std::string aAttributeName ) const
|
||||||
|
{
|
||||||
|
return glGetAttribLocation( programNumber, aAttributeName.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHADER::shaderInfo( GLuint aShader )
|
||||||
|
{
|
||||||
|
GLint glInfoLogLength = 0;
|
||||||
|
GLint writtenChars = 0;
|
||||||
|
|
||||||
|
// Get the length of the info string
|
||||||
|
glGetShaderiv( aShader, GL_INFO_LOG_LENGTH, &glInfoLogLength );
|
||||||
|
|
||||||
|
// Print the information
|
||||||
|
if( glInfoLogLength > 2 )
|
||||||
|
{
|
||||||
|
GLchar* glInfoLog = new GLchar[glInfoLogLength];
|
||||||
|
glGetShaderInfoLog( aShader, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHADER::addSource( const std::string& aShaderSource, SHADER_TYPE aShaderType )
|
||||||
|
{
|
||||||
|
if( isShaderLinked )
|
||||||
|
{
|
||||||
|
wxLogError( wxString::FromUTF8( "Shader is already linked!" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the program
|
||||||
|
if( !isProgramCreated )
|
||||||
|
{
|
||||||
|
programNumber = glCreateProgram();
|
||||||
|
isProgramCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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[aShaderSource.size() + 1];
|
||||||
|
strcpy( source, aShaderSource.c_str() );
|
||||||
|
const char** source_ = (const char**) ( &source );
|
||||||
|
|
||||||
|
// Attach the source
|
||||||
|
glShaderSource( shaderNumber, 1, source_, NULL );
|
||||||
|
programInfo( programNumber );
|
||||||
|
|
||||||
|
// Delete the allocated char array
|
||||||
|
delete[] source;
|
||||||
|
|
||||||
|
// Compile and attach shader to the program
|
||||||
|
glCompileShader( shaderNumber );
|
||||||
|
GLint status;
|
||||||
|
glGetShaderiv( shaderNumber, GL_COMPILE_STATUS, &status );
|
||||||
|
|
||||||
|
if( status != GL_TRUE )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Shader compilation error" ) );
|
||||||
|
|
||||||
|
shaderInfo( shaderNumber );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@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
|
||||||
|
|
||||||
|
// Shader types
|
||||||
|
const float SHADER_LINE = 1.0f;
|
||||||
|
const float SHADER_FILLED_CIRCLE = 2.0f;
|
||||||
|
const float SHADER_STROKED_CIRCLE = 3.0f;
|
||||||
|
|
||||||
|
varying vec4 shaderParams;
|
||||||
|
varying vec2 circleCoords;
|
||||||
|
|
||||||
|
void filledCircle( vec2 aCoord )
|
||||||
|
{
|
||||||
|
if( dot( aCoord, aCoord ) < 1.0f )
|
||||||
|
gl_FragColor = gl_Color;
|
||||||
|
else
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
|
||||||
|
{
|
||||||
|
float outerRadius = aRadius + ( aWidth / 2 );
|
||||||
|
float innerRadius = aRadius - ( aWidth / 2 );
|
||||||
|
float relWidth = innerRadius / outerRadius;
|
||||||
|
|
||||||
|
if( ( dot( aCoord, aCoord ) < 1.0f ) &&
|
||||||
|
( dot( aCoord, aCoord ) > relWidth * relWidth ) )
|
||||||
|
gl_FragColor = gl_Color;
|
||||||
|
else
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
if( shaderParams[0] == SHADER_FILLED_CIRCLE )
|
||||||
|
{
|
||||||
|
filledCircle( circleCoords );
|
||||||
|
}
|
||||||
|
else if( shaderParams[0] == SHADER_STROKED_CIRCLE )
|
||||||
|
{
|
||||||
|
strokedCircle( circleCoords, shaderParams[2], shaderParams[3] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Simple pass-through
|
||||||
|
gl_FragColor = gl_Color;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@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
|
||||||
|
|
||||||
|
// Shader types
|
||||||
|
const float SHADER_LINE = 1.0f;
|
||||||
|
const float SHADER_FILLED_CIRCLE = 2.0f;
|
||||||
|
const float SHADER_STROKED_CIRCLE = 3.0f;
|
||||||
|
|
||||||
|
// Minimum line width
|
||||||
|
const float MIN_WIDTH = 1.0f;
|
||||||
|
|
||||||
|
attribute vec4 attrShaderParams;
|
||||||
|
varying vec4 shaderParams;
|
||||||
|
varying vec2 circleCoords;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Pass attributes to the fragment shader
|
||||||
|
shaderParams = attrShaderParams;
|
||||||
|
|
||||||
|
if( shaderParams[0] == SHADER_LINE )
|
||||||
|
{
|
||||||
|
float lineWidth = shaderParams[3];
|
||||||
|
float worldScale = gl_ModelViewMatrix[0][0];
|
||||||
|
float scale;
|
||||||
|
|
||||||
|
// Make lines appear to be at least 1 pixel wide
|
||||||
|
if( worldScale * lineWidth < MIN_WIDTH )
|
||||||
|
scale = MIN_WIDTH / ( worldScale * lineWidth );
|
||||||
|
else
|
||||||
|
scale = 1.0f;
|
||||||
|
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix *
|
||||||
|
( gl_Vertex + vec4( shaderParams.yz * scale, 0.0, 0.0 ) );
|
||||||
|
}
|
||||||
|
else if( ( shaderParams[0] == SHADER_STROKED_CIRCLE ) ||
|
||||||
|
( shaderParams[0] == SHADER_FILLED_CIRCLE ) )
|
||||||
|
{
|
||||||
|
// Compute relative circle coordinates basing on indices
|
||||||
|
// Circle
|
||||||
|
if( shaderParams[1] == 1.0f )
|
||||||
|
circleCoords = vec2( -sqrt( 3.0f ), -1.0f );
|
||||||
|
else if( shaderParams[1] == 2.0f )
|
||||||
|
circleCoords = vec2( sqrt( 3.0f ), -1.0f );
|
||||||
|
else if( shaderParams[1] == 3.0f )
|
||||||
|
circleCoords = vec2( 0.0f, 2.0f );
|
||||||
|
|
||||||
|
// Semicircle
|
||||||
|
else if( shaderParams[1] == 4.0f )
|
||||||
|
circleCoords = vec2( -3.0f / sqrt( 3.0f ), 0.0f );
|
||||||
|
else if( shaderParams[1] == 5.0f )
|
||||||
|
circleCoords = vec2( 3.0f / sqrt( 3.0f ), 0.0f );
|
||||||
|
else if( shaderParams[1] == 6.0f )
|
||||||
|
circleCoords = vec2( 0.0f, 2.0f );
|
||||||
|
|
||||||
|
// Make the line appear to be at least 1 pixel wide
|
||||||
|
float lineWidth = shaderParams[3];
|
||||||
|
float worldScale = gl_ModelViewMatrix[0][0];
|
||||||
|
|
||||||
|
// Make lines appear to be at least 1 pixel width
|
||||||
|
if( worldScale * lineWidth < MIN_WIDTH )
|
||||||
|
shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
|
||||||
|
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Pass through the coordinates like in the fixed pipeline
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file vertex_container.cpp
|
||||||
|
* @brief Class to store vertices and handle transfers between system memory and GPU memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/vertex_container.h>
|
||||||
|
#include <gal/opengl/cached_container.h>
|
||||||
|
#include <gal/opengl/noncached_container.h>
|
||||||
|
#include <gal/opengl/shader.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
|
||||||
|
{
|
||||||
|
if( aCached )
|
||||||
|
return new CACHED_CONTAINER;
|
||||||
|
else
|
||||||
|
return new NONCACHED_CONTAINER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
|
||||||
|
m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_failed( false )
|
||||||
|
{
|
||||||
|
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX_CONTAINER::~VERTEX_CONTAINER()
|
||||||
|
{
|
||||||
|
free( m_vertices );
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file vertex_item.cpp
|
||||||
|
* @brief Class to handle an item held in a container.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/vertex_item.h>
|
||||||
|
#include <gal/opengl/vertex_manager.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
VERTEX_ITEM::VERTEX_ITEM( const VERTEX_MANAGER& aManager ) :
|
||||||
|
m_manager( aManager ), m_offset( 0 ), m_size( 0 )
|
||||||
|
{
|
||||||
|
// As the item is created, we are going to modify it, so call to SetItem() is needed
|
||||||
|
m_manager.SetItem( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX_ITEM::~VERTEX_ITEM()
|
||||||
|
{
|
||||||
|
m_manager.FreeItem( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX* VERTEX_ITEM::GetVertices() const
|
||||||
|
{
|
||||||
|
return m_manager.GetVertices( *this );
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file vertex_manager.cpp
|
||||||
|
* @brief Class to control vertex container and GPU with possibility of emulating old-style OpenGL
|
||||||
|
* 1.0 state machine using modern OpenGL methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gal/opengl/vertex_manager.h>
|
||||||
|
#include <gal/opengl/cached_container.h>
|
||||||
|
#include <gal/opengl/noncached_container.h>
|
||||||
|
#include <gal/opengl/gpu_manager.h>
|
||||||
|
#include <gal/opengl/vertex_item.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
|
||||||
|
m_noTransform( true ), m_transform( 1.0f )
|
||||||
|
{
|
||||||
|
m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) );
|
||||||
|
m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) );
|
||||||
|
|
||||||
|
// There is no shader used by default
|
||||||
|
for( unsigned int i = 0; i < ShaderStride; ++i )
|
||||||
|
m_shader[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const
|
||||||
|
{
|
||||||
|
// Obtain the pointer to the vertex in the currently used container
|
||||||
|
VERTEX* newVertex = m_container->Allocate( 1 );
|
||||||
|
|
||||||
|
if( newVertex == NULL )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Vertex allocation error" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
putVertex( *newVertex, aX, aY, aZ );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize ) const
|
||||||
|
{
|
||||||
|
// Obtain pointer to the vertex in currently used container
|
||||||
|
VERTEX* newVertex = m_container->Allocate( aSize );
|
||||||
|
|
||||||
|
if( newVertex == NULL )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Vertex allocation error" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put vertices in already allocated memory chunk
|
||||||
|
for( unsigned int i = 0; i < aSize; ++i )
|
||||||
|
{
|
||||||
|
putVertex( newVertex[i], aVertices[i].x, aVertices[i].y, aVertices[i].z );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::SetItem( VERTEX_ITEM& aItem ) const
|
||||||
|
{
|
||||||
|
m_container->SetItem( &aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::FinishItem() const
|
||||||
|
{
|
||||||
|
m_container->FinishItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::FreeItem( VERTEX_ITEM& aItem ) const
|
||||||
|
{
|
||||||
|
m_container->Delete( &aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const
|
||||||
|
{
|
||||||
|
unsigned int size = aItem.GetSize();
|
||||||
|
unsigned int offset = aItem.GetOffset();
|
||||||
|
|
||||||
|
VERTEX* vertex = m_container->GetVertices( offset );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < size; ++i )
|
||||||
|
{
|
||||||
|
vertex->r = aColor.r * 255.0;
|
||||||
|
vertex->g = aColor.g * 255.0;
|
||||||
|
vertex->b = aColor.b * 255.0;
|
||||||
|
vertex->a = aColor.a * 255.0;
|
||||||
|
vertex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_container->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const
|
||||||
|
{
|
||||||
|
unsigned int size = aItem.GetSize();
|
||||||
|
unsigned int offset = aItem.GetOffset();
|
||||||
|
|
||||||
|
VERTEX* vertex = m_container->GetVertices( offset );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < size; ++i )
|
||||||
|
{
|
||||||
|
vertex->z = aDepth;
|
||||||
|
vertex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_container->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEX* VERTEX_MANAGER::GetVertices( const VERTEX_ITEM& aItem ) const
|
||||||
|
{
|
||||||
|
if( aItem.GetSize() == 0 )
|
||||||
|
return NULL; // The item is not stored in the container
|
||||||
|
|
||||||
|
return m_container->GetVertices( aItem.GetOffset() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::SetShader( SHADER& aShader ) const
|
||||||
|
{
|
||||||
|
m_gpu->SetShader( aShader );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::Clear() const
|
||||||
|
{
|
||||||
|
m_container->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::BeginDrawing() const
|
||||||
|
{
|
||||||
|
m_gpu->BeginDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const
|
||||||
|
{
|
||||||
|
int size = aItem.GetSize();
|
||||||
|
|
||||||
|
if( size > 0 )
|
||||||
|
{
|
||||||
|
int offset = aItem.GetOffset();
|
||||||
|
m_gpu->DrawIndices( offset, size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::EndDrawing() const
|
||||||
|
{
|
||||||
|
m_gpu->EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VERTEX_MANAGER::putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const
|
||||||
|
{
|
||||||
|
// Modify the vertex according to the currently used transformations
|
||||||
|
if( m_noTransform )
|
||||||
|
{
|
||||||
|
// Simply copy coordinates, when the transform matrix is the identity matrix
|
||||||
|
aTarget.x = aX;
|
||||||
|
aTarget.y = aY;
|
||||||
|
aTarget.z = aZ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Apply transformations
|
||||||
|
glm::vec4 transVertex( aX, aY, aZ, 1.0f );
|
||||||
|
transVertex = m_transform * transVertex;
|
||||||
|
|
||||||
|
aTarget.x = transVertex.x;
|
||||||
|
aTarget.y = transVertex.y;
|
||||||
|
aTarget.z = transVertex.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply currently used color
|
||||||
|
aTarget.r = m_color[0];
|
||||||
|
aTarget.g = m_color[1];
|
||||||
|
aTarget.b = m_color[2];
|
||||||
|
aTarget.a = m_color[3];
|
||||||
|
|
||||||
|
// Apply currently used shader
|
||||||
|
for( unsigned int j = 0; j < ShaderStride; ++j )
|
||||||
|
{
|
||||||
|
aTarget.shader[j] = m_shader[j];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,305 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
const double STROKE_FONT::LINE_HEIGHT_RATIO = 1.6;
|
||||||
|
|
||||||
|
|
||||||
|
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 = 0.0;
|
||||||
|
double glyphEndX = 0.0;
|
||||||
|
VECTOR2D glyphBoundingX;
|
||||||
|
|
||||||
|
std::deque<VECTOR2D> pointList;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while( aNewStrokeFont[j][i] )
|
||||||
|
{
|
||||||
|
VECTOR2D point( 0.0, 0.0 );
|
||||||
|
char coordinate[2] = { 0, };
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLYPHBoundingX ) const
|
||||||
|
{
|
||||||
|
BOX2D boundingBox;
|
||||||
|
|
||||||
|
std::deque<VECTOR2D> boundingPoints;
|
||||||
|
|
||||||
|
boundingPoints.push_back( VECTOR2D( aGLYPHBoundingX.x, 0 ) );
|
||||||
|
boundingPoints.push_back( VECTOR2D( aGLYPHBoundingX.y, 0 ) );
|
||||||
|
|
||||||
|
for( GLYPH::const_iterator pointListIt = aGLYPH.begin(); pointListIt != aGLYPH.end(); ++pointListIt )
|
||||||
|
{
|
||||||
|
for( std::deque<VECTOR2D>::const_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, const VECTOR2D& aPosition, double aRotationAngle )
|
||||||
|
{
|
||||||
|
// By default overbar is turned off
|
||||||
|
m_overbar = false;
|
||||||
|
|
||||||
|
// Context needs to be saved before any transformations
|
||||||
|
m_gal->Save();
|
||||||
|
|
||||||
|
m_gal->Translate( aPosition );
|
||||||
|
m_gal->Rotate( -aRotationAngle );
|
||||||
|
|
||||||
|
// Split multiline strings into separate ones and draw them line by line
|
||||||
|
size_t newlinePos = aText.find( '\n' );
|
||||||
|
|
||||||
|
if( newlinePos != std::string::npos )
|
||||||
|
{
|
||||||
|
VECTOR2D nextlinePosition = VECTOR2D( 0.0, m_glyphSize.y * LINE_HEIGHT_RATIO );
|
||||||
|
|
||||||
|
Draw( aText.substr( newlinePos + 1 ), nextlinePosition, 0.0 );
|
||||||
|
aText = aText.substr( 0, newlinePos );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the text size
|
||||||
|
VECTOR2D textsize = computeTextSize( aText );
|
||||||
|
|
||||||
|
// Adjust the text position to the given alignment
|
||||||
|
switch( m_horizontalJustify )
|
||||||
|
{
|
||||||
|
case GR_TEXT_HJUSTIFY_CENTER:
|
||||||
|
m_gal->Translate( VECTOR2D( -textsize.x / 2.0, 0 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_HJUSTIFY_RIGHT:
|
||||||
|
if( !m_mirrored )
|
||||||
|
m_gal->Translate( VECTOR2D( -textsize.x, 0 ) );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GR_TEXT_HJUSTIFY_LEFT:
|
||||||
|
if( m_mirrored )
|
||||||
|
m_gal->Translate( VECTOR2D( -textsize.x, 0 ) );
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m_verticalJustify )
|
||||||
|
{
|
||||||
|
case GR_TEXT_VJUSTIFY_CENTER:
|
||||||
|
m_gal->Translate( VECTOR2D( 0, textsize.y / 2.0 ) );
|
||||||
|
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;
|
||||||
|
|
||||||
|
m_gal->SetIsStroke( true );
|
||||||
|
m_gal->SetIsFill( false );
|
||||||
|
|
||||||
|
if( m_bold )
|
||||||
|
{
|
||||||
|
m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ )
|
||||||
|
{
|
||||||
|
if( *chIt == '~' )
|
||||||
|
{
|
||||||
|
m_overbar = !m_overbar;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLYPH_LIST::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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_overbar )
|
||||||
|
{
|
||||||
|
VECTOR2D startOverbar( xOffset, -textsize.y * 1.2 );
|
||||||
|
VECTOR2D endOverbar( xOffset + m_scaleFactor * glyphSizeX * bbIt->GetEnd().x,
|
||||||
|
-textsize.y * 1.2 );
|
||||||
|
m_gal->DrawLine( startOverbar, endOverbar );
|
||||||
|
}
|
||||||
|
|
||||||
|
xOffset += m_scaleFactor * glyphSizeX * bbIt->GetEnd().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gal->Restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VECTOR2D STROKE_FONT::computeTextSize( const std::string& aText ) const
|
||||||
|
{
|
||||||
|
VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y );
|
||||||
|
|
||||||
|
for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ )
|
||||||
|
{
|
||||||
|
if( *chIt == '~' )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::deque<BOX2D>::const_iterator bbIt = m_glyphBoundingBoxes.begin();
|
||||||
|
advance( bbIt, (int) ( *chIt ) - (int) ' ' );
|
||||||
|
result.x += m_scaleFactor * m_glyphSize.x * bbIt->GetEnd().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* 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 <geometry/seg.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int sgn( T aVal )
|
||||||
|
{
|
||||||
|
return ( T( 0 ) < aVal ) - ( aVal < T( 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const
|
||||||
|
{
|
||||||
|
VECTOR2I d = B - A;
|
||||||
|
ecoord dist_sq = (ecoord) aDist * aDist;
|
||||||
|
|
||||||
|
SEG::ecoord l_squared = d.Dot( d );
|
||||||
|
SEG::ecoord t = d.Dot( aP - A );
|
||||||
|
|
||||||
|
if( t <= 0 || !l_squared )
|
||||||
|
return ( aP - A ).SquaredEuclideanNorm() < dist_sq;
|
||||||
|
else if( t >= l_squared )
|
||||||
|
return ( aP - B ).SquaredEuclideanNorm() < dist_sq;
|
||||||
|
|
||||||
|
int dxdy = abs( d.x ) - abs( d.y );
|
||||||
|
|
||||||
|
if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 )
|
||||||
|
{
|
||||||
|
int ca = -sgn( d.y );
|
||||||
|
int cb = sgn( d.x );
|
||||||
|
int cc = -ca * A.x - cb * A.y;
|
||||||
|
|
||||||
|
ecoord num = ca * aP.x + cb * aP.y + cc;
|
||||||
|
num *= num;
|
||||||
|
|
||||||
|
if( ca && cb )
|
||||||
|
num >>= 1;
|
||||||
|
|
||||||
|
if( num > ( dist_sq + 100 ) )
|
||||||
|
return false;
|
||||||
|
else if( num < ( dist_sq - 100 ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VECTOR2I nearest;
|
||||||
|
nearest.x = A.x + rescale( t, (ecoord) d.x, l_squared );
|
||||||
|
nearest.y = A.y + rescale( t, (ecoord) d.y, l_squared );
|
||||||
|
|
||||||
|
return ( nearest - aP ).SquaredEuclideanNorm() <= dist_sq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const
|
||||||
|
{
|
||||||
|
// fixme: rather inefficient....
|
||||||
|
if( Intersect( aSeg ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const VECTOR2I pts[4] =
|
||||||
|
{
|
||||||
|
aSeg.NearestPoint( A ) - A,
|
||||||
|
aSeg.NearestPoint( B ) - B,
|
||||||
|
NearestPoint( aSeg.A ) - aSeg.A,
|
||||||
|
NearestPoint( aSeg.B ) - aSeg.B
|
||||||
|
};
|
||||||
|
|
||||||
|
ecoord m = VECTOR2I::ECOORD_MAX;
|
||||||
|
|
||||||
|
for( int i = 0; i < 4; i++ )
|
||||||
|
m = std::min( m, pts[i].SquaredEuclideanNorm() );
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const
|
||||||
|
{
|
||||||
|
const VECTOR2I e( B - A );
|
||||||
|
const VECTOR2I f( aSeg.B - aSeg.A );
|
||||||
|
const VECTOR2I ac( aSeg.A - A );
|
||||||
|
|
||||||
|
ecoord d = f.Cross( e );
|
||||||
|
ecoord p = f.Cross( ac );
|
||||||
|
ecoord q = e.Cross( ac );
|
||||||
|
|
||||||
|
if( d == 0 )
|
||||||
|
return OPT_VECTOR2I();
|
||||||
|
|
||||||
|
if( !aLines && d > 0 && ( q < 0 || q > d || p < 0 || p > d ) )
|
||||||
|
return OPT_VECTOR2I();
|
||||||
|
|
||||||
|
if( !aLines && d < 0 && ( q < d || p < d || p > 0 || q > 0 ) )
|
||||||
|
return OPT_VECTOR2I();
|
||||||
|
|
||||||
|
if( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) )
|
||||||
|
return OPT_VECTOR2I();
|
||||||
|
|
||||||
|
VECTOR2I ip( aSeg.A.x + rescale( q, (ecoord) f.x, d ),
|
||||||
|
aSeg.A.y + rescale( q, (ecoord) f.y, d ) );
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SEG::ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ) const
|
||||||
|
{
|
||||||
|
return (ecoord) ( aC.y - aA.y ) * ( aB.x - aA.x ) > (ecoord) ( aB.y - aA.y ) * ( aC.x - aA.x );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SEG::Collide( const SEG& aSeg, int aClearance ) const
|
||||||
|
{
|
||||||
|
// check for intersection
|
||||||
|
// fixme: move to a method
|
||||||
|
if( ccw( A, aSeg.A, aSeg.B ) != ccw( B, aSeg.A, aSeg.B ) &&
|
||||||
|
ccw( A, B, aSeg.A ) != ccw( A, B, aSeg.B ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#define CHK( _seg, _pt ) \
|
||||||
|
if( (_seg).PointCloserThan( _pt, aClearance ) ) return true;
|
||||||
|
|
||||||
|
CHK( *this, aSeg.A );
|
||||||
|
CHK( *this, aSeg.B );
|
||||||
|
CHK( aSeg, A );
|
||||||
|
CHK( aSeg, B );
|
||||||
|
#undef CHK
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SEG::Contains( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
return PointCloserThan( aP, 1 );
|
||||||
|
}
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* 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 <math/vector2d.h>
|
||||||
|
|
||||||
|
#include <geometry/shape.h>
|
||||||
|
#include <geometry/shape_line_chain.h>
|
||||||
|
#include <geometry/shape_circle.h>
|
||||||
|
#include <geometry/shape_rect.h>
|
||||||
|
|
||||||
|
typedef VECTOR2I::extended_type ecoord;
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
ecoord min_dist = aClearance + aA.GetRadius() + aB.GetRadius();
|
||||||
|
ecoord min_dist_sq = min_dist * min_dist;
|
||||||
|
|
||||||
|
const VECTOR2I delta = aB.GetCenter() - aA.GetCenter();
|
||||||
|
|
||||||
|
ecoord dist_sq = delta.SquaredEuclideanNorm();
|
||||||
|
|
||||||
|
if( dist_sq >= min_dist_sq )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( aNeedMTV )
|
||||||
|
aMTV = delta.Resize( sqrt( abs( min_dist_sq - dist_sq ) ) + 1 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
const VECTOR2I c = aB.GetCenter();
|
||||||
|
const VECTOR2I p0 = aA.GetPosition();
|
||||||
|
const VECTOR2I size = aA.GetSize();
|
||||||
|
const ecoord r = aB.GetRadius();
|
||||||
|
const ecoord min_dist = aClearance + r;
|
||||||
|
const ecoord min_dist_sq = min_dist * min_dist;
|
||||||
|
|
||||||
|
if( aA.BBox( 0 ).Contains( c ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const VECTOR2I vts[] =
|
||||||
|
{
|
||||||
|
VECTOR2I( p0.x, p0.y ),
|
||||||
|
VECTOR2I( p0.x, p0.y + size.y ),
|
||||||
|
VECTOR2I( p0.x + size.x, p0.y + size.y ),
|
||||||
|
VECTOR2I( p0.x + size.x, p0.y ),
|
||||||
|
VECTOR2I( p0.x, p0.y )
|
||||||
|
};
|
||||||
|
|
||||||
|
ecoord nearest_seg_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||||
|
VECTOR2I nearest;
|
||||||
|
|
||||||
|
bool inside = c.x >= p0.x && c.x <= ( p0.x + size.x )
|
||||||
|
&& c.y >= p0.y && c.y <= ( p0.y + size.y );
|
||||||
|
|
||||||
|
if( !inside )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; i++ )
|
||||||
|
{
|
||||||
|
const SEG seg( vts[i], vts[i + 1] );
|
||||||
|
ecoord dist_sq = seg.SquaredDistance( c );
|
||||||
|
|
||||||
|
if( dist_sq < min_dist_sq )
|
||||||
|
{
|
||||||
|
if( !aNeedMTV )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nearest = seg.NearestPoint( c );
|
||||||
|
nearest_seg_dist_sq = dist_sq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( nearest_seg_dist_sq >= min_dist_sq && !inside )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
VECTOR2I delta = c - nearest;
|
||||||
|
|
||||||
|
if( !aNeedMTV )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( inside )
|
||||||
|
aMTV = -delta.Resize( sqrt( abs( r * r + nearest_seg_dist_sq ) + 1 ) );
|
||||||
|
else
|
||||||
|
aMTV = delta.Resize( sqrt( abs( r * r - nearest_seg_dist_sq ) + 1 ) );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
for( int s = 0; s < aB.SegmentCount(); s++ )
|
||||||
|
{
|
||||||
|
if( aA.Collide( aB.CSegment( s ), aClearance ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < aB.SegmentCount(); i++ )
|
||||||
|
if( aA.Collide( aB.CSegment( i ), aClearance ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
for( int s = 0; s < aB.SegmentCount(); s++ )
|
||||||
|
{
|
||||||
|
SEG seg = aB.CSegment( s );
|
||||||
|
|
||||||
|
if( aA.Collide( seg, aClearance ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
switch( aA->Type() )
|
||||||
|
{
|
||||||
|
case SH_RECT:
|
||||||
|
switch( aB->Type() )
|
||||||
|
{
|
||||||
|
case SH_CIRCLE:
|
||||||
|
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
|
||||||
|
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
case SH_LINE_CHAIN:
|
||||||
|
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
|
||||||
|
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SH_CIRCLE:
|
||||||
|
switch( aB->Type() )
|
||||||
|
{
|
||||||
|
case SH_RECT:
|
||||||
|
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
|
||||||
|
*static_cast<const SHAPE_CIRCLE*>( aA ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
case SH_CIRCLE:
|
||||||
|
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
|
||||||
|
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
case SH_LINE_CHAIN:
|
||||||
|
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
|
||||||
|
*static_cast<const SHAPE_LINE_CHAIN *>( aB ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SH_LINE_CHAIN:
|
||||||
|
switch( aB->Type() )
|
||||||
|
{
|
||||||
|
case SH_RECT:
|
||||||
|
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
|
||||||
|
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
case SH_CIRCLE:
|
||||||
|
return Collide( *static_cast<const SHAPE_CIRCLE*>( aB ),
|
||||||
|
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
case SH_LINE_CHAIN:
|
||||||
|
return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( aA ),
|
||||||
|
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unsupported_collision = true;
|
||||||
|
|
||||||
|
assert( unsupported_collision == false );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE::Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const
|
||||||
|
{
|
||||||
|
return CollideShapes( this, aShape, aClerance, true, aMTV );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE::Collide( const SHAPE* aShape, int aClerance ) const
|
||||||
|
{
|
||||||
|
VECTOR2I dummy;
|
||||||
|
|
||||||
|
return CollideShapes( this, aShape, aClerance, false, dummy );
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @author Jacobo Aragunde Pérez
|
||||||
|
* @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 <geometry/shape_index.h>
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const SHAPE* shapeFunctor( SHAPE* aItem )
|
||||||
|
{
|
||||||
|
return aItem;
|
||||||
|
}
|
|
@ -0,0 +1,537 @@
|
||||||
|
/*
|
||||||
|
* 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 <geometry/shape_line_chain.h>
|
||||||
|
#include <geometry/shape_circle.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using boost::optional;
|
||||||
|
|
||||||
|
bool SHAPE_LINE_CHAIN::Collide( const VECTOR2I& aP, int aClearance ) const
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE_LINE_CHAIN::Collide( const BOX2I& aBox, int aClearance ) const
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance ) const
|
||||||
|
{
|
||||||
|
BOX2I box_a( aSeg.A, aSeg.B - aSeg.A );
|
||||||
|
BOX2I::ecoord_type dist_sq = (BOX2I::ecoord_type) aClearance * aClearance;
|
||||||
|
|
||||||
|
for( int i = 0; i < SegmentCount(); i++ )
|
||||||
|
{
|
||||||
|
const SEG& s = CSegment( i );
|
||||||
|
BOX2I box_b( s.A, s.B - s.A );
|
||||||
|
|
||||||
|
BOX2I::ecoord_type d = box_a.SquaredDistance( box_b );
|
||||||
|
|
||||||
|
if( d < dist_sq )
|
||||||
|
{
|
||||||
|
if( s.Collide( aSeg, aClearance ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
|
||||||
|
{
|
||||||
|
SHAPE_LINE_CHAIN a( *this );
|
||||||
|
|
||||||
|
reverse( a.m_points.begin(), a.m_points.end() );
|
||||||
|
a.m_closed = m_closed;
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Length() const
|
||||||
|
{
|
||||||
|
int l = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < SegmentCount(); i++ )
|
||||||
|
l += CSegment( i ).Length();
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP )
|
||||||
|
{
|
||||||
|
if( aEndIndex < 0 )
|
||||||
|
aEndIndex += PointCount();
|
||||||
|
|
||||||
|
if( aStartIndex < 0 )
|
||||||
|
aStartIndex += PointCount();
|
||||||
|
|
||||||
|
if( aStartIndex == aEndIndex )
|
||||||
|
m_points[aStartIndex] = aP;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 );
|
||||||
|
m_points[aStartIndex] = aP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine )
|
||||||
|
{
|
||||||
|
if( aEndIndex < 0 )
|
||||||
|
aEndIndex += PointCount();
|
||||||
|
|
||||||
|
if( aStartIndex < 0 )
|
||||||
|
aStartIndex += PointCount();
|
||||||
|
|
||||||
|
m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
|
||||||
|
m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
|
||||||
|
{
|
||||||
|
if( aEndIndex < 0 )
|
||||||
|
aEndIndex += PointCount();
|
||||||
|
|
||||||
|
if( aStartIndex < 0 )
|
||||||
|
aStartIndex += PointCount();
|
||||||
|
|
||||||
|
m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
int d = INT_MAX;
|
||||||
|
|
||||||
|
for( int s = 0; s < SegmentCount(); s++ )
|
||||||
|
d = min( d, CSegment( s ).Distance( aP ) );
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
|
||||||
|
{
|
||||||
|
int ii = -1;
|
||||||
|
int min_dist = 2;
|
||||||
|
|
||||||
|
ii = Find( aP );
|
||||||
|
|
||||||
|
if( ii >= 0 )
|
||||||
|
return ii;
|
||||||
|
|
||||||
|
for( int s = 0; s < SegmentCount(); s++ )
|
||||||
|
{
|
||||||
|
const SEG seg = CSegment( s );
|
||||||
|
int dist = seg.Distance( aP );
|
||||||
|
|
||||||
|
// make sure we are not producing a 'slightly concave' primitive. This might happen
|
||||||
|
// if aP lies very close to one of already existing points.
|
||||||
|
if( dist < min_dist && seg.A != aP && seg.B != aP )
|
||||||
|
{
|
||||||
|
min_dist = dist;
|
||||||
|
ii = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ii >= 0 )
|
||||||
|
{
|
||||||
|
m_points.insert( m_points.begin() + ii + 1, aP );
|
||||||
|
|
||||||
|
return ii + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
for( int s = 0; s< PointCount(); s++ )
|
||||||
|
if( CPoint( s ) == aP )
|
||||||
|
return s;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
|
||||||
|
{
|
||||||
|
SHAPE_LINE_CHAIN rv;
|
||||||
|
|
||||||
|
if( aEndIndex < 0 )
|
||||||
|
aEndIndex += PointCount();
|
||||||
|
|
||||||
|
if( aStartIndex < 0 )
|
||||||
|
aStartIndex += PointCount();
|
||||||
|
|
||||||
|
for( int i = aStartIndex; i <= aEndIndex; i++ )
|
||||||
|
rv.Append( m_points[i] );
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct compareOriginDistance
|
||||||
|
{
|
||||||
|
compareOriginDistance( VECTOR2I& aOrigin ) :
|
||||||
|
m_origin( aOrigin ) {};
|
||||||
|
|
||||||
|
bool operator()( const SHAPE_LINE_CHAIN::INTERSECTION& aA,
|
||||||
|
const SHAPE_LINE_CHAIN::INTERSECTION& aB )
|
||||||
|
{
|
||||||
|
return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm();
|
||||||
|
}
|
||||||
|
|
||||||
|
VECTOR2I m_origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Intersect( const SEG& aSeg, INTERSECTIONS& aIp ) const
|
||||||
|
{
|
||||||
|
for( int s = 0; s < SegmentCount(); s++ )
|
||||||
|
{
|
||||||
|
OPT_VECTOR2I p = CSegment( s ).Intersect( aSeg );
|
||||||
|
|
||||||
|
if( p )
|
||||||
|
{
|
||||||
|
INTERSECTION is;
|
||||||
|
is.our = CSegment( s );
|
||||||
|
is.their = aSeg;
|
||||||
|
is.p = *p;
|
||||||
|
aIp.push_back( is );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compareOriginDistance comp( aSeg.A );
|
||||||
|
sort( aIp.begin(), aIp.end(), comp );
|
||||||
|
|
||||||
|
return aIp.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp ) const
|
||||||
|
{
|
||||||
|
BOX2I bb_other = aChain.BBox();
|
||||||
|
|
||||||
|
for( int s1 = 0; s1 < SegmentCount(); s1++ )
|
||||||
|
{
|
||||||
|
const SEG& a = CSegment( s1 );
|
||||||
|
const BOX2I bb_cur( a.A, a.B - a.A );
|
||||||
|
|
||||||
|
if( !bb_other.Intersects( bb_cur ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
|
||||||
|
{
|
||||||
|
const SEG& b = aChain.CSegment( s2 );
|
||||||
|
INTERSECTION is;
|
||||||
|
|
||||||
|
if( a.Collinear( b ) )
|
||||||
|
{
|
||||||
|
if( a.Contains( b.A ) ) { is.p = b.A; aIp.push_back( is ); }
|
||||||
|
if( a.Contains( b.B ) ) { is.p = b.B; aIp.push_back( is ); }
|
||||||
|
if( b.Contains( a.A ) ) { is.p = a.A; aIp.push_back( is ); }
|
||||||
|
if( b.Contains( a.B ) ) { is.p = a.B; aIp.push_back( is ); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OPT_VECTOR2I p = a.Intersect( b );
|
||||||
|
|
||||||
|
if( p )
|
||||||
|
{
|
||||||
|
is.p = *p;
|
||||||
|
is.our = a;
|
||||||
|
is.their = b;
|
||||||
|
aIp.push_back( is );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aIp.size();
|
||||||
|
|
||||||
|
for( int s1 = 0; s1 < SegmentCount(); s1++ )
|
||||||
|
{
|
||||||
|
for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
|
||||||
|
{
|
||||||
|
const SEG& a = CSegment( s1 );
|
||||||
|
const SEG& b = aChain.CSegment( s2 );
|
||||||
|
OPT_VECTOR2I p = a.Intersect( b );
|
||||||
|
INTERSECTION is;
|
||||||
|
|
||||||
|
if( p )
|
||||||
|
{
|
||||||
|
is.p = *p;
|
||||||
|
is.our = a;
|
||||||
|
is.their = b;
|
||||||
|
aIp.push_back( is );
|
||||||
|
}
|
||||||
|
else if( a.Collinear( b ) )
|
||||||
|
{
|
||||||
|
if( a.A != b.A && a.A != b.B && b.Contains( a.A ) )
|
||||||
|
{
|
||||||
|
is.p = a.A;
|
||||||
|
is.our = a;
|
||||||
|
is.their = b;
|
||||||
|
aIp.push_back( is );
|
||||||
|
}
|
||||||
|
else if( a.B != b.A && a.B != b.B && b.Contains( a.B ) )
|
||||||
|
{
|
||||||
|
is.p = a.B;
|
||||||
|
is.our = a;
|
||||||
|
is.their = b;
|
||||||
|
aIp.push_back( is );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aIp.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < SegmentCount(); i++ )
|
||||||
|
{
|
||||||
|
const SEG seg = CSegment( i );
|
||||||
|
int d = seg.Distance( aP );
|
||||||
|
|
||||||
|
if( d <= 1 )
|
||||||
|
{
|
||||||
|
sum += ( aP - seg.A ).EuclideanNorm();
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sum += seg.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
if( !m_closed || SegmentCount() < 3 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int cur = CSegment( 0 ).Side( aP );
|
||||||
|
|
||||||
|
if( cur == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( int i = 1; i < SegmentCount(); i++ )
|
||||||
|
{
|
||||||
|
const SEG s = CSegment( i );
|
||||||
|
|
||||||
|
if( aP == s.A || aP == s.B ) // edge does not belong to the interior!
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( s.Side( aP ) != cur )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
if( SegmentCount() < 1 )
|
||||||
|
return m_points[0] == aP;
|
||||||
|
|
||||||
|
for( int i = 1; i < SegmentCount(); i++ )
|
||||||
|
{
|
||||||
|
const SEG s = CSegment( i );
|
||||||
|
|
||||||
|
if( s.A == aP || s.B == aP )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( s.Distance( aP ) <= 1 )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const optional<SHAPE_LINE_CHAIN::INTERSECTION> SHAPE_LINE_CHAIN::SelfIntersecting() const
|
||||||
|
{
|
||||||
|
for( int s1 = 0; s1 < SegmentCount(); s1++ )
|
||||||
|
{
|
||||||
|
for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ )
|
||||||
|
{
|
||||||
|
const VECTOR2I s2a = CSegment( s2 ).A, s2b = CSegment( s2 ).B;
|
||||||
|
|
||||||
|
if( s1 + 1 != s2 && CSegment( s1 ).Contains( s2a ) )
|
||||||
|
{
|
||||||
|
INTERSECTION is;
|
||||||
|
is.our = CSegment( s1 );
|
||||||
|
is.their = CSegment( s2 );
|
||||||
|
is.p = s2a;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
else if( CSegment( s1 ).Contains( s2b ) )
|
||||||
|
{
|
||||||
|
INTERSECTION is;
|
||||||
|
is.our = CSegment( s1 );
|
||||||
|
is.their = CSegment( s2 );
|
||||||
|
is.p = s2b;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true );
|
||||||
|
|
||||||
|
if( p )
|
||||||
|
{
|
||||||
|
INTERSECTION is;
|
||||||
|
is.our = CSegment( s1 );
|
||||||
|
is.their = CSegment( s2 );
|
||||||
|
is.p = *p;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return optional<INTERSECTION>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||||
|
{
|
||||||
|
vector<VECTOR2I> pts_unique;
|
||||||
|
|
||||||
|
if( PointCount() < 2 )
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
else if( PointCount() == 2 )
|
||||||
|
{
|
||||||
|
if( m_points[0] == m_points[1] )
|
||||||
|
m_points.erase( m_points.end() );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int np = PointCount();
|
||||||
|
|
||||||
|
// stage 1: eliminate duplicate vertices
|
||||||
|
while( i < np )
|
||||||
|
{
|
||||||
|
int j = i + 1;
|
||||||
|
|
||||||
|
while( j < np && CPoint( i ) == CPoint( j ) )
|
||||||
|
j++;
|
||||||
|
|
||||||
|
pts_unique.push_back( CPoint( i ) );
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_points.clear();
|
||||||
|
np = pts_unique.size();
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// stage 1: eliminate collinear segments
|
||||||
|
while( i < np - 2 )
|
||||||
|
{
|
||||||
|
const VECTOR2I p0 = pts_unique[i];
|
||||||
|
const VECTOR2I p1 = pts_unique[i + 1];
|
||||||
|
int n = i;
|
||||||
|
|
||||||
|
while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 )
|
||||||
|
n++;
|
||||||
|
|
||||||
|
m_points.push_back( p0 );
|
||||||
|
|
||||||
|
if( n > i )
|
||||||
|
i = n;
|
||||||
|
|
||||||
|
if( n == np )
|
||||||
|
{
|
||||||
|
m_points.push_back( pts_unique[n - 1] );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( np > 1 )
|
||||||
|
m_points.push_back( pts_unique[np - 2] );
|
||||||
|
|
||||||
|
m_points.push_back( pts_unique[np - 1] );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
int min_d = INT_MAX;
|
||||||
|
int nearest = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < SegmentCount(); i++ )
|
||||||
|
{
|
||||||
|
int d = CSegment( i ).Distance( aP );
|
||||||
|
|
||||||
|
if( d < min_d )
|
||||||
|
{
|
||||||
|
min_d = d;
|
||||||
|
nearest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CSegment( nearest ).NearestPoint( aP );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string SHAPE_LINE_CHAIN::Format() const
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
|
||||||
|
ss << m_points.size() << " " << ( m_closed ? 1 : 0 ) << " ";
|
||||||
|
|
||||||
|
for( int i = 0; i < PointCount(); i++ )
|
||||||
|
ss << m_points[i].x << " " << m_points[i].y << " "; // Format() << " ";
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
|
@ -1488,12 +1488,12 @@ bool ColorIsLight( EDA_COLOR_T aColor )
|
||||||
|
|
||||||
EDA_COLOR_T ColorFindNearest( const wxColour &aColor )
|
EDA_COLOR_T ColorFindNearest( const wxColour &aColor )
|
||||||
{
|
{
|
||||||
EDA_COLOR_T candidate = BLACK;
|
return ColorFindNearest( aColor.Red(), aColor.Green(), aColor.Blue() );
|
||||||
|
}
|
||||||
|
|
||||||
// These are ints because we will subtract them later
|
EDA_COLOR_T ColorFindNearest( int aR, int aG, int aB )
|
||||||
int r = aColor.Red();
|
{
|
||||||
int g = aColor.Green();
|
EDA_COLOR_T candidate = BLACK;
|
||||||
int b = aColor.Blue();
|
|
||||||
|
|
||||||
/* Find the 'nearest' color in the palette. This is fun. There is
|
/* Find the 'nearest' color in the palette. This is fun. There is
|
||||||
a gazilion of metrics for the color space and no one of the
|
a gazilion of metrics for the color space and no one of the
|
||||||
|
@ -1511,11 +1511,11 @@ EDA_COLOR_T ColorFindNearest( const wxColour &aColor )
|
||||||
for( EDA_COLOR_T trying = BLACK; trying < NBCOLORS; trying = NextColor(trying) )
|
for( EDA_COLOR_T trying = BLACK; trying < NBCOLORS; trying = NextColor(trying) )
|
||||||
{
|
{
|
||||||
const StructColors &c = g_ColorRefs[trying];
|
const StructColors &c = g_ColorRefs[trying];
|
||||||
int distance = (r - c.m_Red) * (r - c.m_Red) +
|
int distance = (aR - c.m_Red) * (aR - c.m_Red) +
|
||||||
(g - c.m_Green) * (g - c.m_Green) +
|
(aG - c.m_Green) * (aG - c.m_Green) +
|
||||||
(b - c.m_Blue) * (b - c.m_Blue);
|
(aB - c.m_Blue) * (aB - c.m_Blue);
|
||||||
if( distance < nearest_distance && c.m_Red >= r &&
|
if( distance < nearest_distance && c.m_Red >= aR &&
|
||||||
c.m_Green >= g && c.m_Blue >= b )
|
c.m_Green >= aG && c.m_Blue >= aB )
|
||||||
{
|
{
|
||||||
nearest_distance = distance;
|
nearest_distance = distance;
|
||||||
candidate = trying;
|
candidate = trying;
|
||||||
|
|
|
@ -65,7 +65,7 @@ void GRID_TRICKS::getSelectedArea()
|
||||||
wxArrayInt cols = m_grid->GetSelectedCols();
|
wxArrayInt cols = m_grid->GetSelectedCols();
|
||||||
wxArrayInt rows = m_grid->GetSelectedRows();
|
wxArrayInt rows = m_grid->GetSelectedRows();
|
||||||
|
|
||||||
D(printf("topLeft.Count():%zd botRight:Count():%zd\n", topLeft.Count(), botRight.Count() );)
|
DBG(printf("topLeft.Count():%zd botRight:Count():%zd\n", topLeft.Count(), botRight.Count() );)
|
||||||
|
|
||||||
if( topLeft.Count() && botRight.Count() )
|
if( topLeft.Count() && botRight.Count() )
|
||||||
{
|
{
|
||||||
|
@ -97,7 +97,7 @@ void GRID_TRICKS::getSelectedArea()
|
||||||
m_sel_col_count = 0;
|
m_sel_col_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//D(printf("m_sel_row_start:%d m_sel_col_start:%d m_sel_row_count:%d m_sel_col_count:%d\n", m_sel_row_start, m_sel_col_start, m_sel_row_count, m_sel_col_count );)
|
//DBG(printf("m_sel_row_start:%d m_sel_col_start:%d m_sel_row_count:%d m_sel_col_count:%d\n", m_sel_row_start, m_sel_col_start, m_sel_row_count, m_sel_col_count );)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
* Copyright (C) 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 <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <climits>
|
||||||
|
#include <math/math_util.h>
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int rescale( int aNumerator, int aValue, int aDenominator )
|
||||||
|
{
|
||||||
|
return (int) ( (int64_t) aNumerator * (int64_t) aValue / (int64_t) aDenominator );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int64_t rescale( int64_t aNumerator, int64_t aValue, int64_t aDenominator )
|
||||||
|
{
|
||||||
|
int64_t r = 0;
|
||||||
|
int64_t sign = ( ( aNumerator < 0 ) ? -1 : 1 ) * ( aDenominator < 0 ? -1 : 1 ) *
|
||||||
|
( aValue < 0 ? -1 : 1 );
|
||||||
|
|
||||||
|
int64_t a = std::abs( aNumerator );
|
||||||
|
int64_t b = std::abs( aValue );
|
||||||
|
int64_t c = std::abs( aDenominator );
|
||||||
|
|
||||||
|
r = c / 2;
|
||||||
|
|
||||||
|
if( b <= INT_MAX && c <= INT_MAX )
|
||||||
|
{
|
||||||
|
if( a <= INT_MAX )
|
||||||
|
return sign * ( ( a * b + r ) / c );
|
||||||
|
else
|
||||||
|
return sign * ( a / c * b + ( a % c * b + r ) / c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t a0 = a & 0xFFFFFFFF;
|
||||||
|
uint64_t a1 = a >> 32;
|
||||||
|
uint64_t b0 = b & 0xFFFFFFFF;
|
||||||
|
uint64_t b1 = b >> 32;
|
||||||
|
uint64_t t1 = a0 * b1 + a1 * b0;
|
||||||
|
uint64_t t1a = t1 << 32;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
a0 = a0 * b0 + t1a;
|
||||||
|
a1 = a1 * b1 + ( t1 >> 32 ) + ( a0 < t1a );
|
||||||
|
a0 += r;
|
||||||
|
a1 += ( (uint64_t) a0 ) < r;
|
||||||
|
|
||||||
|
for( i = 63; i >= 0; i-- )
|
||||||
|
{
|
||||||
|
a1 += a1 + ( ( a0 >> i ) & 1 );
|
||||||
|
t1 += t1;
|
||||||
|
|
||||||
|
if( (uint64_t) c <= a1 )
|
||||||
|
{
|
||||||
|
a1 -= c;
|
||||||
|
t1++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t1 * sign;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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 <painter.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
RENDER_SETTINGS::RENDER_SETTINGS()
|
||||||
|
{
|
||||||
|
// Set the default initial values
|
||||||
|
m_highlightFactor = 0.5;
|
||||||
|
m_selectFactor = 0.5;
|
||||||
|
m_layerOpacity = 0.8;
|
||||||
|
m_highlightEnabled = false;
|
||||||
|
m_hiContrastEnabled = false;
|
||||||
|
m_hiContrastFactor = 0.2;
|
||||||
|
m_outlineWidth = 1;
|
||||||
|
m_worksheetLineWidth = 100000;
|
||||||
|
|
||||||
|
// Store the predefined colors used in KiCad in format used by GAL
|
||||||
|
for( int i = 0; i < NBCOLORS; i++ )
|
||||||
|
{
|
||||||
|
m_legacyColorMap[g_ColorRefs[i].m_Numcolor] = COLOR4D( (double) g_ColorRefs[i].m_Red / 255.0,
|
||||||
|
(double) g_ColorRefs[i].m_Green / 255.0,
|
||||||
|
(double) g_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_brightenedColor( 0.0, 1.0, 0.0, 0.9 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PAINTER::~PAINTER()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PAINTER::SetGAL( GAL* aGal )
|
||||||
|
{
|
||||||
|
m_gal = aGal;
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TPROFILE_H
|
||||||
|
#define __TPROFILE_H
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#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 microseconds that have elapsed since the system was started.
|
||||||
|
* @return uint64_t Number of microseconds.
|
||||||
|
*/
|
||||||
|
static inline uint64_t get_tics()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday( &tv, NULL );
|
||||||
|
|
||||||
|
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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. IMPORTANT: time-stamp counter should not
|
||||||
|
* be used on multicore machines executing threaded code.
|
||||||
|
*/
|
||||||
|
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
|
|
@ -39,8 +39,6 @@
|
||||||
#include <protos.h>
|
#include <protos.h>
|
||||||
|
|
||||||
|
|
||||||
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
|
|
||||||
|
|
||||||
const wxString traceFindItem( wxT( "KicadFindItem" ) );
|
const wxString traceFindItem( wxT( "KicadFindItem" ) );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
Boost::Context assembly wrapper - done to avoid compiling the whole boost binary library
|
||||||
|
which may be unpleasant, in particular under Windows (we don't support VC++, while boost::context
|
||||||
|
does not support mingw */
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
#include "jump_i386_sysv_macho_gas.S"
|
||||||
|
#include "make_i386_sysv_macho_gas.S"
|
||||||
|
|
||||||
|
#elif __x86_64__
|
||||||
|
#include "jump_x86_64_sysv_macho_gas.S"
|
||||||
|
#include "make_x86_64_sysv_macho_gas.S"
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Missing make_fcontext & jump_fcontext routines for this architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
|
#include "jump_i386_pe_gas.S"
|
||||||
|
#include "make_i386_pe_gas.S"
|
||||||
|
#else
|
||||||
|
#include "jump_i386_sysv_elf_gas.S"
|
||||||
|
#include "make_i386_sysv_elf_gas.S"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif __x86_64__
|
||||||
|
#include "jump_x86_64_sysv_elf_gas.S"
|
||||||
|
#include "make_x86_64_sysv_elf_gas.S"
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Missing make_fcontext & jump_fcontext routines for this architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global _jump_fcontext
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
_jump_fcontext:
|
||||||
|
mov 0x4(%esp),%ecx
|
||||||
|
mov %edi,(%ecx)
|
||||||
|
mov %esi,0x4(%ecx)
|
||||||
|
mov %ebx,0x8(%ecx)
|
||||||
|
mov %ebp,0xc(%ecx)
|
||||||
|
mov %fs:0x18,%edx
|
||||||
|
mov (%edx),%eax
|
||||||
|
mov %eax,0x24(%ecx)
|
||||||
|
mov 0x4(%edx),%eax
|
||||||
|
mov %eax,0x18(%ecx)
|
||||||
|
mov 0x8(%edx),%eax
|
||||||
|
mov %eax,0x20(%ecx)
|
||||||
|
mov 0x10(%edx),%eax
|
||||||
|
mov %eax,0x28(%ecx)
|
||||||
|
lea 0x4(%esp),%eax
|
||||||
|
mov %eax,0x10(%ecx)
|
||||||
|
mov (%esp),%eax
|
||||||
|
mov %eax,0x14(%ecx)
|
||||||
|
mov 0x8(%esp),%edx
|
||||||
|
mov (%edx),%edi
|
||||||
|
mov 0x4(%edx),%esi
|
||||||
|
mov 0x8(%edx),%ebx
|
||||||
|
mov 0xc(%edx),%ebp
|
||||||
|
mov 0x10(%esp),%eax
|
||||||
|
test %eax,%eax
|
||||||
|
je _jump_fcontext+0x5f
|
||||||
|
stmxcsr 0x2c(%ecx)
|
||||||
|
fnstcw 0x30(%ecx)
|
||||||
|
ldmxcsr 0x2c(%edx)
|
||||||
|
fldcw 0x30(%edx)
|
||||||
|
mov %edx,%ecx
|
||||||
|
mov %fs:0x18,%edx
|
||||||
|
mov 0x24(%ecx),%eax
|
||||||
|
mov %eax,(%edx)
|
||||||
|
mov 0x18(%ecx),%eax
|
||||||
|
mov %eax,0x4(%edx)
|
||||||
|
mov 0x20(%ecx),%eax
|
||||||
|
mov %eax,0x8(%edx)
|
||||||
|
mov 0x28(%ecx),%eax
|
||||||
|
mov %eax,0x10(%edx)
|
||||||
|
mov 0xc(%esp),%eax
|
||||||
|
mov 0x10(%ecx),%esp
|
||||||
|
mov %eax,0x4(%esp)
|
||||||
|
mov 0x14(%ecx),%ecx
|
||||||
|
jmp *%ecx
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 6 | 7 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x18 | 0x1c | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* *****************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl jump_fcontext
|
||||||
|
.align 2
|
||||||
|
.type jump_fcontext,@function
|
||||||
|
jump_fcontext:
|
||||||
|
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
|
||||||
|
movl %edi, (%ecx) /* save EDI */
|
||||||
|
movl %esi, 0x4(%ecx) /* save ESI */
|
||||||
|
movl %ebx, 0x8(%ecx) /* save EBX */
|
||||||
|
movl %ebp, 0xc(%ecx) /* save EBP */
|
||||||
|
|
||||||
|
leal 0x4(%esp), %eax /* exclude the return address */
|
||||||
|
movl %eax, 0x10(%ecx) /* save as stack pointer */
|
||||||
|
movl (%esp), %eax /* load return address */
|
||||||
|
movl %eax, 0x14(%ecx) /* save return address */
|
||||||
|
|
||||||
|
movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */
|
||||||
|
movl (%edx), %edi /* restore EDI */
|
||||||
|
movl 0x4(%edx), %esi /* restore ESI */
|
||||||
|
movl 0x8(%edx), %ebx /* restore EBX */
|
||||||
|
movl 0xc(%edx), %ebp /* restore EBP */
|
||||||
|
|
||||||
|
movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */
|
||||||
|
test %eax, %eax
|
||||||
|
je 1f
|
||||||
|
|
||||||
|
stmxcsr 0x20(%ecx) /* save MMX control and status word */
|
||||||
|
fnstcw 0x24(%ecx) /* save x87 control word */
|
||||||
|
ldmxcsr 0x20(%edx) /* restore MMX control and status word */
|
||||||
|
fldcw 0x24(%edx) /* restore x87 control word */
|
||||||
|
1:
|
||||||
|
movl 0xc(%esp), %eax /* use third arg as return value after jump */
|
||||||
|
|
||||||
|
movl 0x10(%edx), %esp /* restore ESP */
|
||||||
|
movl %eax, 0x4(%esp) /* use third arg as first arg in context function */
|
||||||
|
movl 0x14(%edx), %edx /* fetch the address to return to */
|
||||||
|
|
||||||
|
jmp *%edx /* indirect jump to context */
|
||||||
|
.size jump_fcontext,.-jump_fcontext
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 6 | 7 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x18 | 0x1c | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* *****************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _jump_fcontext
|
||||||
|
.align 2
|
||||||
|
_jump_fcontext:
|
||||||
|
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
|
||||||
|
movl %edi, (%ecx) /* save EDI */
|
||||||
|
movl %esi, 0x4(%ecx) /* save ESI */
|
||||||
|
movl %ebx, 0x8(%ecx) /* save EBX */
|
||||||
|
movl %ebp, 0xc(%ecx) /* save EBP */
|
||||||
|
|
||||||
|
leal 0x4(%esp), %eax /* exclude the return address */
|
||||||
|
movl %eax, 0x10(%ecx) /* save as stack pointer */
|
||||||
|
movl (%esp), %eax /* load return address */
|
||||||
|
movl %eax, 0x14(%ecx) /* save return address */
|
||||||
|
|
||||||
|
movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */
|
||||||
|
movl (%edx), %edi /* restore EDI */
|
||||||
|
movl 0x4(%edx), %esi /* restore ESI */
|
||||||
|
movl 0x8(%edx), %ebx /* restore EBX */
|
||||||
|
movl 0xc(%edx), %ebp /* restore EBP */
|
||||||
|
|
||||||
|
movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */
|
||||||
|
test %eax, %eax
|
||||||
|
je 1f
|
||||||
|
|
||||||
|
stmxcsr 0x20(%ecx) /* save MMX control and status word */
|
||||||
|
fnstcw 0x24(%ecx) /* save x87 control word */
|
||||||
|
ldmxcsr 0x20(%edx) /* restore MMX control and status word */
|
||||||
|
fldcw 0x24(%edx) /* restore x87 control word */
|
||||||
|
1:
|
||||||
|
movl 0xc(%esp), %eax /* use third arg as return value after jump */
|
||||||
|
|
||||||
|
movl 0x10(%edx), %esp /* restore ESP */
|
||||||
|
movl %eax, 0x4(%esp) /* use third arg as first arg in context function */
|
||||||
|
movl 0x14(%edx), %edx /* fetch the address to return to */
|
||||||
|
|
||||||
|
jmp *%edx /* indirect jump to context */
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | RBX | R12 | R13 | R14 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | R15 | RBP | RSP | RIP | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 16 | 17 | 18 | 19 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 20 | 21 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x50 | 0x54 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* **************************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl jump_fcontext
|
||||||
|
.type jump_fcontext,@function
|
||||||
|
.align 8
|
||||||
|
jump_fcontext:
|
||||||
|
movq %rbx, (%rdi) /* save RBX */
|
||||||
|
movq %r12, 0x8(%rdi) /* save R12 */
|
||||||
|
movq %r13, 0x10(%rdi) /* save R13 */
|
||||||
|
movq %r14, 0x18(%rdi) /* save R14 */
|
||||||
|
movq %r15, 0x20(%rdi) /* save R15 */
|
||||||
|
movq %rbp, 0x28(%rdi) /* save RBP */
|
||||||
|
|
||||||
|
cmp $0, %rcx
|
||||||
|
je 1f
|
||||||
|
|
||||||
|
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
||||||
|
fnstcw 0x54(%rdi) /* save x87 control word */
|
||||||
|
|
||||||
|
ldmxcsr 0x50(%rsi) /* restore MMX control and status word */
|
||||||
|
fldcw 0x54(%rsi) /* restore x87 control word */
|
||||||
|
1:
|
||||||
|
|
||||||
|
leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */
|
||||||
|
movq %rax, 0x30(%rdi) /* save as stack pointer */
|
||||||
|
movq (%rsp), %rax /* save return address */
|
||||||
|
movq %rax, 0x38(%rdi) /* save return address as RIP */
|
||||||
|
|
||||||
|
movq (%rsi), %rbx /* restore RBX */
|
||||||
|
movq 0x8(%rsi), %r12 /* restore R12 */
|
||||||
|
movq 0x10(%rsi), %r13 /* restore R13 */
|
||||||
|
movq 0x18(%rsi), %r14 /* restore R14 */
|
||||||
|
movq 0x20(%rsi), %r15 /* restore R15 */
|
||||||
|
movq 0x28(%rsi), %rbp /* restore RBP */
|
||||||
|
|
||||||
|
movq 0x30(%rsi), %rsp /* restore RSP */
|
||||||
|
movq 0x38(%rsi), %rcx /* fetch the address to return to */
|
||||||
|
|
||||||
|
movq %rdx, %rax /* use third arg as return value after jump */
|
||||||
|
movq %rdx, %rdi /* use third arg as first arg in context function */
|
||||||
|
|
||||||
|
jmp *%rcx /* indirect jump to context */
|
||||||
|
.size jump_fcontext,.-jump_fcontext
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | RBX | R12 | R13 | R14 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | R15 | RBP | RSP | RIP | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 16 | 17 | 18 | 19 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 20 | 21 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x50 | 0x54 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* **************************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _jump_fcontext
|
||||||
|
.align 8
|
||||||
|
_jump_fcontext:
|
||||||
|
movq %rbx, (%rdi) /* save RBX */
|
||||||
|
movq %r12, 0x8(%rdi) /* save R12 */
|
||||||
|
movq %r13, 0x10(%rdi) /* save R13 */
|
||||||
|
movq %r14, 0x18(%rdi) /* save R14 */
|
||||||
|
movq %r15, 0x20(%rdi) /* save R15 */
|
||||||
|
movq %rbp, 0x28(%rdi) /* save RBP */
|
||||||
|
|
||||||
|
cmp $0, %rcx
|
||||||
|
je 1f
|
||||||
|
|
||||||
|
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
||||||
|
fnstcw 0x54(%rdi) /* save x87 control word */
|
||||||
|
|
||||||
|
ldmxcsr 0x50(%rsi) /* restore MMX control and status word */
|
||||||
|
fldcw 0x54(%rsi) /* restore x87 control word */
|
||||||
|
1:
|
||||||
|
|
||||||
|
leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */
|
||||||
|
movq %rax, 0x30(%rdi) /* save as stack pointer */
|
||||||
|
movq (%rsp), %rax /* save return address */
|
||||||
|
movq %rax, 0x38(%rdi) /* save return address as RIP */
|
||||||
|
|
||||||
|
movq (%rsi), %rbx /* restore RBX */
|
||||||
|
movq 0x8(%rsi), %r12 /* restore R12 */
|
||||||
|
movq 0x10(%rsi), %r13 /* restore R13 */
|
||||||
|
movq 0x18(%rsi), %r14 /* restore R14 */
|
||||||
|
movq 0x20(%rsi), %r15 /* restore R15 */
|
||||||
|
movq 0x28(%rsi), %rbp /* restore RBP */
|
||||||
|
|
||||||
|
movq 0x30(%rsi), %rsp /* restore RSP */
|
||||||
|
movq 0x38(%rsi), %rcx /* fetch the address to return to */
|
||||||
|
|
||||||
|
movq %rdx, %rax /* use third arg as return value after jump */
|
||||||
|
movq %rdx, %rdi /* use third arg as first arg in context function */
|
||||||
|
|
||||||
|
jmp *%rcx /* indirect jump to context */
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global _make_fcontext
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
_make_fcontext:
|
||||||
|
mov 0x4(%esp),%eax
|
||||||
|
lea -0x34(%eax),%eax
|
||||||
|
and $0xfffffff0,%eax
|
||||||
|
mov 0x4(%esp),%ecx
|
||||||
|
mov %ecx,0x18(%eax)
|
||||||
|
mov 0x8(%esp),%edx
|
||||||
|
mov %edx,0x1c(%eax)
|
||||||
|
neg %edx
|
||||||
|
lea (%edx,%ecx,1),%ecx
|
||||||
|
mov %ecx,0x20(%eax)
|
||||||
|
mov 0xc(%esp),%ecx
|
||||||
|
mov %ecx,0x14(%eax)
|
||||||
|
stmxcsr 0x2c(%eax)
|
||||||
|
fnstcw 0x30(%eax)
|
||||||
|
lea -0x1c(%eax),%edx
|
||||||
|
mov %edx,0x10(%eax)
|
||||||
|
mov $0x0,%ecx
|
||||||
|
mov %ecx,(%edx)
|
||||||
|
mov %fs:0x18,%ecx
|
||||||
|
mov (%ecx),%edx
|
||||||
|
inc %edx
|
||||||
|
je _make_fcontext+0x4c // <_make_fcontext+0x4c>
|
||||||
|
dec %edx
|
||||||
|
xchg %edx,%ecx
|
||||||
|
jmp _make_fcontext+0x42 // <_make_fcontext+0x42>
|
||||||
|
mov 0x4(%ecx),%ecx
|
||||||
|
mov 0x10(%eax),%edx
|
||||||
|
mov %ecx,0x18(%edx)
|
||||||
|
mov $0xffffffff,%ecx
|
||||||
|
mov %ecx,0x14(%edx)
|
||||||
|
lea 0x14(%edx),%ecx
|
||||||
|
mov %ecx,0x24(%eax)
|
||||||
|
ret
|
||||||
|
|
||||||
|
finish:
|
||||||
|
xor %eax,%eax
|
||||||
|
mov %eax,(%esp)
|
||||||
|
call finish+0xa
|
||||||
|
hlt
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 6 | 7 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x18 | 0x1c | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* *****************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl make_fcontext
|
||||||
|
.align 2
|
||||||
|
.type make_fcontext,@function
|
||||||
|
make_fcontext:
|
||||||
|
movl 0x4(%esp), %eax /* load 1. arg of make_fcontext, pointer to context stack (base) */
|
||||||
|
leal -0x28(%eax), %eax /* reserve space for fcontext_t at top of context stack */
|
||||||
|
|
||||||
|
/* shift address in EAX to lower 16 byte boundary */
|
||||||
|
/* == pointer to fcontext_t and address of context stack */
|
||||||
|
andl $-16, %eax
|
||||||
|
|
||||||
|
movl 0x4(%esp), %edx /* load 1. arg of make_fcontext, pointer to context stack (base) */
|
||||||
|
movl %edx, 0x18(%eax) /* save address of context stack (base) in fcontext_t */
|
||||||
|
movl 0x8(%esp), %edx /* load 2. arg of make_fcontext, context stack size */
|
||||||
|
movl %edx, 0x1c(%eax) /* save stack size in fcontext_t */
|
||||||
|
movl 0xc(%esp), %edx /* load 3. arg of make_fcontext, pointer to context function */
|
||||||
|
movl %edx, 0x14(%eax) /* save address of context function in fcontext_t */
|
||||||
|
|
||||||
|
stmxcsr 0x20(%eax) /* save MMX control and status word */
|
||||||
|
fnstcw 0x24(%eax) /* save x87 control word */
|
||||||
|
|
||||||
|
leal -0x8(%eax), %edx /* reserve space for the last frame on context stack; (ESP - 0x4) % 16 == 0 */
|
||||||
|
movl %edx, 0x10(%eax) /* save address in EDX as stack pointer for context function */
|
||||||
|
|
||||||
|
call 1f
|
||||||
|
1: popl %ecx /* address of label 2 */
|
||||||
|
addl $finish-1b, %ecx /* compute abs address of label finish */
|
||||||
|
movl %ecx, (%edx) /* save address of finish as return address for context functions */
|
||||||
|
/* entered after context function returns */
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* ESP points to same address as ESP on entry of context function + 0x4 */
|
||||||
|
call 2f
|
||||||
|
2: popl %ebx /* address of label 3 */
|
||||||
|
addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %ebx /* compute address of GOT and store it in EBX */
|
||||||
|
|
||||||
|
xorl %eax, %eax
|
||||||
|
movl %eax, (%esp) /* exit code is zero */
|
||||||
|
call _exit@PLT /* exit application */
|
||||||
|
hlt
|
||||||
|
.size make_fcontext,.-make_fcontext
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 6 | 7 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x18 | 0x1c | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* -------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* *****************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _make_fcontext
|
||||||
|
.align 2
|
||||||
|
_make_fcontext:
|
||||||
|
movl 0x4(%esp), %eax /* load 1. arg of make_fcontext, pointer to context stack (base) */
|
||||||
|
leal -0x28(%eax), %eax /* reserve space for fcontext_t at top of context stack */
|
||||||
|
|
||||||
|
/* shift address in EAX to lower 16 byte boundary */
|
||||||
|
/* == pointer to fcontext_t and address of context stack */
|
||||||
|
andl $-16, %eax
|
||||||
|
|
||||||
|
movl 0x4(%esp), %edx /* load 1. arg of make_fcontext, pointer to context stack (base) */
|
||||||
|
movl %edx, 0x18(%eax) /* save address of stack pointer (base) in fcontext_t */
|
||||||
|
movl 0x8(%esp), %edx /* load 2. arg of make_fcontext, context stack size */
|
||||||
|
movl %edx, 0x1c(%eax) /* save stack size in fcontext_t */
|
||||||
|
movl 0xc(%esp), %edx /* load 3. arg of make_fcontext, pointer to context function */
|
||||||
|
movl %edx, 0x14(%eax) /* save address of context fcuntion in fcontext_t */
|
||||||
|
|
||||||
|
stmxcsr 0x20(%eax) /* save MMX control and status word */
|
||||||
|
fnstcw 0x24(%eax) /* save x87 control word */
|
||||||
|
|
||||||
|
leal -0x14(%eax), %edx /* reserve space for the last frame on context stack */
|
||||||
|
movl %edx, 0x10(%eax) /* save address in EDX as stack pointer for context function */
|
||||||
|
|
||||||
|
call 1f
|
||||||
|
1: popl %ecx /* address of label 1 */
|
||||||
|
addl $finish-1b, %ecx /* compute abs address of label finish */
|
||||||
|
movl %ecx, (%edx) /* save address of finish as return address for context function */
|
||||||
|
/* entered after context function returns */
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* ESP points to same address as ESP on entry of context function + 0x4 */
|
||||||
|
xorl %eax, %eax
|
||||||
|
movl %eax, (%esp) /* exit code is zero */
|
||||||
|
call __exit /* exit application */
|
||||||
|
hlt
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | RBX | R12 | R13 | R14 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | R15 | RBP | RSP | RIP | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 16 | 17 | 18 | 19 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 20 | 21 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x50 | 0x54 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* **************************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl make_fcontext
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
.type make_fcontext,@function
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
make_fcontext:
|
||||||
|
leaq -0x58(%rdi), %rax /* reserve space for fcontext_t at top of context stack */
|
||||||
|
|
||||||
|
/* shift address in RAX to lower 16 byte boundary */
|
||||||
|
/* == pointer to fcontext_t and address of context stack */
|
||||||
|
andq $-16, %rax
|
||||||
|
|
||||||
|
movq %rdi, 0x40(%rax) /* save address of context stack pointer (base) in fcontext_t */
|
||||||
|
movq %rsi, 0x48(%rax) /* save context stack size in fcontext_t */
|
||||||
|
movq %rdx, 0x38(%rax) /* save address of context function in fcontext_t */
|
||||||
|
|
||||||
|
stmxcsr 0x50(%rax) /* save MMX control and status word */
|
||||||
|
fnstcw 0x54(%rax) /* save x87 control word */
|
||||||
|
|
||||||
|
leaq -0x8(%rax), %rdx /* reserve space for the return address on context stack, (RSP - 0x8) % 16 == 0 */
|
||||||
|
movq %rdx, 0x30(%rax) /* save address in RDX as stack pointer for context function */
|
||||||
|
|
||||||
|
leaq finish(%rip), %rcx /* compute abs address of label finish */
|
||||||
|
movq %rcx, (%rdx) /* save address of finish as return address for context function */
|
||||||
|
/* entered after context function returns */
|
||||||
|
|
||||||
|
ret /* return pointer to fcontext_t placed on context stack */
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* RSP points to same address as RSP on entry of context function + 0x8 */
|
||||||
|
xorq %rdi, %rdi /* exit code is zero */
|
||||||
|
call _exit@PLT /* exit application */
|
||||||
|
hlt
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
.size make_fcontext,.-make_fcontext
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright Oliver Kowalke 2009.
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | RBX | R12 | R13 | R14 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | R15 | RBP | RSP | RIP | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 16 | 17 | 18 | 19 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | sp | size | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 20 | 21 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | 0x50 | 0x54 | | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* | fc_mxcsr|fc_x87_cw| | *
|
||||||
|
* ---------------------------------------------------------------------------------- *
|
||||||
|
* *
|
||||||
|
* **************************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _make_fcontext
|
||||||
|
.align 8
|
||||||
|
_make_fcontext:
|
||||||
|
leaq -0x58(%rdi), %rax /* reserve space for fcontext_t at top of context stack */
|
||||||
|
|
||||||
|
/* shift address in RAX to lower 16 byte boundary */
|
||||||
|
/* == pointer to fcontext_t and address of context stack */
|
||||||
|
movabs $-16, %r8
|
||||||
|
andq %r8, %rax
|
||||||
|
|
||||||
|
movq %rdi, 0x40(%rax) /* save address of stack pointer (base) in fcontext_t */
|
||||||
|
movq %rsi, 0x48(%rax) /* save stack size in fcontext_t */
|
||||||
|
movq %rdx, 0x38(%rax) /* save address of context function in fcontext_t */
|
||||||
|
|
||||||
|
stmxcsr 0x50(%rax) /* save MMX control and status word */
|
||||||
|
fnstcw 0x54(%rax) /* save x87 control word */
|
||||||
|
|
||||||
|
leaq -0x8(%rax), %rdx /* reserve space for the return address on context stack, (RSP - 0x8) % 16 == 0 */
|
||||||
|
movq %rdx, 0x30(%rax) /* save address in RDX as stack pointer for context function */
|
||||||
|
|
||||||
|
leaq finish(%rip), %rcx /* compute abs address of label finish */
|
||||||
|
movq %rcx, (%rdx) /* save address of finish as return address for context function */
|
||||||
|
/* entered after context function returns */
|
||||||
|
|
||||||
|
ret /* return pointer to fcontext_t placed on context stack */
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* RSP points to same address as RSP on entry of context function + 0x8 */
|
||||||
|
xorq %rdi, %rdi /* exit code is zero */
|
||||||
|
call __exit /* exit application */
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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 <tool/action_manager.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tool/tool_event.h>
|
||||||
|
#include <tool/tool_action.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
|
||||||
|
m_toolMgr( aToolManager )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
assert( aAction->GetId() == -1 ); // Check if the TOOL_ACTION was not registered before
|
||||||
|
|
||||||
|
aAction->setId( MakeActionId( aAction->m_name ) );
|
||||||
|
|
||||||
|
m_actionNameIndex[aAction->m_name] = aAction;
|
||||||
|
m_actionIdIndex[aAction->m_id] = aAction;
|
||||||
|
|
||||||
|
if( aAction->HasHotKey() )
|
||||||
|
m_actionHotKeys[aAction->m_currentHotKey] = aAction;
|
||||||
|
|
||||||
|
aAction->setActionMgr( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
// Indicate that the ACTION_MANAGER no longer care about the object
|
||||||
|
aAction->setActionMgr( NULL );
|
||||||
|
aAction->setId( -1 );
|
||||||
|
|
||||||
|
m_actionNameIndex.erase( aAction->m_name );
|
||||||
|
m_actionIdIndex.erase( aAction->m_id );
|
||||||
|
|
||||||
|
if( aAction->HasHotKey() )
|
||||||
|
m_actionHotKeys.erase( aAction->m_currentHotKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ACTION_MANAGER::MakeActionId( const std::string& aActionName )
|
||||||
|
{
|
||||||
|
static int currentActionId = 1;
|
||||||
|
|
||||||
|
return currentActionId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ACTION_MANAGER::RunAction( const std::string& aActionName ) const
|
||||||
|
{
|
||||||
|
std::map<std::string, TOOL_ACTION*>::const_iterator it = m_actionNameIndex.find( aActionName );
|
||||||
|
|
||||||
|
if( it == m_actionNameIndex.end() )
|
||||||
|
return false; // no action with given name found
|
||||||
|
|
||||||
|
runAction( it->second );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ACTION_MANAGER::RunHotKey( int aHotKey ) const
|
||||||
|
{
|
||||||
|
std::map<int, TOOL_ACTION*>::const_iterator it = m_actionHotKeys.find( aHotKey );
|
||||||
|
|
||||||
|
if( it == m_actionHotKeys.end() )
|
||||||
|
return false; // no appropriate action found for the hotkey
|
||||||
|
|
||||||
|
runAction( it->second );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_MANAGER::runAction( const TOOL_ACTION* aAction ) const
|
||||||
|
{
|
||||||
|
TOOL_EVENT event = aAction->MakeEvent();
|
||||||
|
|
||||||
|
m_toolMgr->ProcessEvent( event );
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* 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 <tool/tool_event.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tool/tool_interactive.h>
|
||||||
|
#include <tool/context_menu.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
CONTEXT_MENU::CONTEXT_MENU() :
|
||||||
|
m_titleSet( false ), m_handler( this ), m_tool( NULL )
|
||||||
|
{
|
||||||
|
m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
|
||||||
|
NULL, &m_handler );
|
||||||
|
m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
|
||||||
|
NULL, &m_handler );
|
||||||
|
|
||||||
|
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
|
||||||
|
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu );
|
||||||
|
m_menu.AddPendingEvent( menuEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
|
||||||
|
m_titleSet( aMenu.m_titleSet ), m_handler( this ), m_tool( aMenu.m_tool )
|
||||||
|
{
|
||||||
|
m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
|
||||||
|
NULL, &m_handler );
|
||||||
|
m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
|
||||||
|
NULL, &m_handler );
|
||||||
|
|
||||||
|
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
|
||||||
|
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu );
|
||||||
|
m_menu.AddPendingEvent( menuEvent );
|
||||||
|
|
||||||
|
// Copy all the menu entries
|
||||||
|
for( unsigned i = 0; i < aMenu.m_menu.GetMenuItemCount(); ++i )
|
||||||
|
{
|
||||||
|
wxMenuItem* item = aMenu.m_menu.FindItemByPosition( i );
|
||||||
|
m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(),
|
||||||
|
wxEmptyString, wxITEM_NORMAL ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy tool actions that are available to choose from context menu
|
||||||
|
m_toolActions = aMenu.m_toolActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CONTEXT_MENU::SetTitle( const wxString& aTitle )
|
||||||
|
{
|
||||||
|
// TODO handle an empty string (remove title and separator)
|
||||||
|
|
||||||
|
// Unfortunately wxMenu::SetTitle() does nothing..
|
||||||
|
if( m_titleSet )
|
||||||
|
{
|
||||||
|
m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_menu.InsertSeparator( 0 );
|
||||||
|
m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) );
|
||||||
|
m_titleSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CONTEXT_MENU::Add( const wxString& aLabel, int aId )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
if( m_menu.FindItem( aId ) != NULL )
|
||||||
|
wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in"
|
||||||
|
"undefined behaviour" ) );
|
||||||
|
#endif
|
||||||
|
m_menu.Append( new wxMenuItem( &m_menu, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
|
||||||
|
{
|
||||||
|
/// ID numbers for tool actions need to have a value higher than m_actionId
|
||||||
|
int id = m_actionId + aAction.GetId();
|
||||||
|
wxString menuEntry;
|
||||||
|
|
||||||
|
if( aAction.HasHotKey() )
|
||||||
|
menuEntry = wxString( ( aAction.GetMenuItem() + '\t' +
|
||||||
|
getHotKeyDescription( aAction ) ).c_str(), wxConvUTF8 );
|
||||||
|
else
|
||||||
|
menuEntry = wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 );
|
||||||
|
|
||||||
|
m_menu.Append( new wxMenuItem( &m_menu, id, menuEntry,
|
||||||
|
wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL ) );
|
||||||
|
|
||||||
|
m_toolActions[id] = &aAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CONTEXT_MENU::Clear()
|
||||||
|
{
|
||||||
|
m_titleSet = false;
|
||||||
|
|
||||||
|
// Remove all the entries from context menu
|
||||||
|
for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i )
|
||||||
|
m_menu.Destroy( m_menu.FindItemByPosition( 0 ) );
|
||||||
|
|
||||||
|
m_toolActions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string CONTEXT_MENU::getHotKeyDescription( const TOOL_ACTION& aAction ) const
|
||||||
|
{
|
||||||
|
int hotkey = aAction.GetHotKey();
|
||||||
|
|
||||||
|
std::string description = "";
|
||||||
|
|
||||||
|
if( hotkey & MD_ALT )
|
||||||
|
description += "ALT+";
|
||||||
|
|
||||||
|
if( hotkey & MD_CTRL )
|
||||||
|
description += "CTRL+";
|
||||||
|
|
||||||
|
if( hotkey & MD_SHIFT )
|
||||||
|
description += "SHIFT+";
|
||||||
|
|
||||||
|
// TODO dispatch keys such as Fx, TAB, PG_UP/DN, HOME, END, etc.
|
||||||
|
description += char( hotkey & ~MD_MODIFIER_MASK );
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
|
||||||
|
{
|
||||||
|
TOOL_EVENT evt;
|
||||||
|
wxEventType type = aEvent.GetEventType();
|
||||||
|
|
||||||
|
// When the currently chosen item in the menu is changed, an update event is issued.
|
||||||
|
// For example, the selection tool can use this to dynamically highlight the current item
|
||||||
|
// from selection clarification popup.
|
||||||
|
if( type == wxEVT_MENU_HIGHLIGHT )
|
||||||
|
evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_UPDATE, aEvent.GetId() );
|
||||||
|
|
||||||
|
// One of menu entries was selected..
|
||||||
|
else if( type == wxEVT_COMMAND_MENU_SELECTED )
|
||||||
|
{
|
||||||
|
// Check if there is a TOOL_ACTION for the given ID
|
||||||
|
if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 )
|
||||||
|
{
|
||||||
|
evt = m_menu->m_toolActions[aEvent.GetId()]->MakeEvent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handling non-action menu entries (e.g. items in clarification list)
|
||||||
|
evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// forward the action/update event to the TOOL_MANAGER
|
||||||
|
if( m_menu->m_tool )
|
||||||
|
m_menu->m_tool->GetManager()->ProcessEvent( evt );
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 <tool/tool_event.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
|
||||||
|
KIGFX::VIEW* TOOL_BASE::getView() const
|
||||||
|
{
|
||||||
|
return m_toolMgr->GetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KIGFX::VIEW_CONTROLS* TOOL_BASE::getViewControls() const
|
||||||
|
{
|
||||||
|
return m_toolMgr->GetViewControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxWindow* TOOL_BASE::getEditFrameInt() const
|
||||||
|
{
|
||||||
|
return m_toolMgr->GetEditFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDA_ITEM* TOOL_BASE::getModelInt() const
|
||||||
|
{
|
||||||
|
return m_toolMgr->GetModel();
|
||||||
|
}
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* 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 <wxPcbStruct.h>
|
||||||
|
#include <wxBasePcbFrame.h>
|
||||||
|
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tool/tool_dispatcher.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
#include <view/wx_view_controls.h>
|
||||||
|
|
||||||
|
#include <class_drawpanel_gal.h>
|
||||||
|
|
||||||
|
#include <pcbnew_id.h>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
using boost::optional;
|
||||||
|
|
||||||
|
///> Stores information about a mouse button state
|
||||||
|
struct TOOL_DISPATCHER::BUTTON_STATE
|
||||||
|
{
|
||||||
|
BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
|
||||||
|
const wxEventType& aUpEvent ) :
|
||||||
|
button( aButton ),
|
||||||
|
downEvent( aDownEvent ),
|
||||||
|
upEvent( aUpEvent )
|
||||||
|
{};
|
||||||
|
|
||||||
|
///> Flag indicating that dragging is active for the given button.
|
||||||
|
bool dragging;
|
||||||
|
|
||||||
|
///> Flag indicating that the given button is pressed.
|
||||||
|
bool pressed;
|
||||||
|
|
||||||
|
///> Point where dragging has started (in world coordinates).
|
||||||
|
VECTOR2D dragOrigin;
|
||||||
|
|
||||||
|
///> Point where click event has occurred.
|
||||||
|
VECTOR2D downPosition;
|
||||||
|
|
||||||
|
///> Difference between drag origin point and current mouse position (expressed as distance in
|
||||||
|
///> pixels).
|
||||||
|
double dragMaxDelta;
|
||||||
|
|
||||||
|
///> Determines the mouse button for which information are stored.
|
||||||
|
TOOL_MOUSE_BUTTONS button;
|
||||||
|
|
||||||
|
///> The type of wxEvent that determines mouse button press.
|
||||||
|
wxEventType downEvent;
|
||||||
|
|
||||||
|
///> The type of wxEvent that determines mouse button release.
|
||||||
|
wxEventType upEvent;
|
||||||
|
|
||||||
|
///> Time stamp for the last mouse button press event.
|
||||||
|
wxLongLong downTimestamp;
|
||||||
|
|
||||||
|
///> Restores initial state.
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
dragging = false;
|
||||||
|
pressed = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditFrame ) :
|
||||||
|
m_toolMgr( aToolMgr ), m_editFrame( aEditFrame )
|
||||||
|
{
|
||||||
|
m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN, wxEVT_LEFT_UP ) );
|
||||||
|
m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_UP ) );
|
||||||
|
m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN, wxEVT_MIDDLE_UP ) );
|
||||||
|
|
||||||
|
ResetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_DISPATCHER::~TOOL_DISPATCHER()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( BUTTON_STATE* st, m_buttons )
|
||||||
|
delete st;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_DISPATCHER::ResetState()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( BUTTON_STATE* st, m_buttons )
|
||||||
|
st->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KIGFX::VIEW* TOOL_DISPATCHER::getView()
|
||||||
|
{
|
||||||
|
return m_editFrame->GetGalCanvas()->GetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
|
||||||
|
{
|
||||||
|
BUTTON_STATE* st = m_buttons[aIndex];
|
||||||
|
wxEventType type = aEvent.GetEventType();
|
||||||
|
optional<TOOL_EVENT> evt;
|
||||||
|
bool isClick = false;
|
||||||
|
|
||||||
|
bool up = type == st->upEvent;
|
||||||
|
bool down = type == st->downEvent;
|
||||||
|
|
||||||
|
int mods = decodeModifiers<wxMouseEvent>( static_cast<wxMouseEvent*>( &aEvent ) );
|
||||||
|
int args = st->button | mods;
|
||||||
|
|
||||||
|
if( down ) // Handle mouse button press
|
||||||
|
{
|
||||||
|
st->downTimestamp = wxGetLocalTimeMillis();
|
||||||
|
st->dragOrigin = m_lastMousePos;
|
||||||
|
st->downPosition = m_lastMousePos;
|
||||||
|
st->dragMaxDelta = 0;
|
||||||
|
st->pressed = true;
|
||||||
|
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
|
||||||
|
}
|
||||||
|
else if( up ) // Handle mouse button release
|
||||||
|
{
|
||||||
|
st->pressed = false;
|
||||||
|
|
||||||
|
if( st->dragging )
|
||||||
|
{
|
||||||
|
wxLongLong t = wxGetLocalTimeMillis();
|
||||||
|
|
||||||
|
// Determine if it was just a single click or beginning of dragging
|
||||||
|
if( t - st->downTimestamp < DragTimeThreshold &&
|
||||||
|
st->dragMaxDelta < DragDistanceThreshold )
|
||||||
|
isClick = true;
|
||||||
|
else
|
||||||
|
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
isClick = true;
|
||||||
|
|
||||||
|
if( isClick )
|
||||||
|
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
|
||||||
|
|
||||||
|
st->dragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( st->pressed && aMotion )
|
||||||
|
{
|
||||||
|
st->dragging = true;
|
||||||
|
double dragPixelDistance =
|
||||||
|
getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm();
|
||||||
|
st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
|
||||||
|
|
||||||
|
wxLongLong t = wxGetLocalTimeMillis();
|
||||||
|
|
||||||
|
if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold )
|
||||||
|
{
|
||||||
|
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
|
||||||
|
evt->SetMouseDragOrigin( st->dragOrigin );
|
||||||
|
evt->SetMouseDelta( m_lastMousePos - st->dragOrigin );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( evt )
|
||||||
|
{
|
||||||
|
evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
|
||||||
|
m_toolMgr->ProcessEvent( *evt );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||||
|
{
|
||||||
|
bool motion = false, buttonEvents = false;
|
||||||
|
optional<TOOL_EVENT> evt;
|
||||||
|
|
||||||
|
int type = aEvent.GetEventType();
|
||||||
|
|
||||||
|
// Mouse handling
|
||||||
|
if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
|
||||||
|
type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
|
||||||
|
type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
|
||||||
|
type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
|
||||||
|
// Event issued whem mouse retains position in screen coordinates,
|
||||||
|
// but changes in world coordinates (eg. autopanning)
|
||||||
|
type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
|
||||||
|
{
|
||||||
|
VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetCursorPosition();
|
||||||
|
VECTOR2D pos = getView()->ToWorld( screenPos );
|
||||||
|
|
||||||
|
if( pos != m_lastMousePos || type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
|
||||||
|
{
|
||||||
|
motion = true;
|
||||||
|
m_lastMousePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < m_buttons.size(); i++ )
|
||||||
|
buttonEvents |= handleMouseButton( aEvent, i, motion );
|
||||||
|
|
||||||
|
if( !buttonEvents && motion )
|
||||||
|
{
|
||||||
|
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION );
|
||||||
|
evt->SetMousePosition( pos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard handling
|
||||||
|
else if( type == wxEVT_KEY_UP || type == wxEVT_KEY_DOWN )
|
||||||
|
{
|
||||||
|
wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
|
||||||
|
int key = ke->GetKeyCode();
|
||||||
|
int mods = decodeModifiers<wxKeyEvent>( ke );
|
||||||
|
|
||||||
|
if( type == wxEVT_KEY_UP )
|
||||||
|
{
|
||||||
|
if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
|
||||||
|
evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL );
|
||||||
|
else
|
||||||
|
evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_UP, key | mods );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_DOWN, key | mods );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( evt )
|
||||||
|
m_toolMgr->ProcessEvent( *evt );
|
||||||
|
|
||||||
|
// pass the event to the GUI, it might still be interested in it
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
bool activateTool = false;
|
||||||
|
std::string toolName;
|
||||||
|
|
||||||
|
// fixme: use TOOL_ACTIONs here
|
||||||
|
switch( aEvent.GetId() )
|
||||||
|
{
|
||||||
|
case ID_PNS_ROUTER_TOOL:
|
||||||
|
toolName = "pcbnew.InteractiveRouter";
|
||||||
|
activateTool = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ID_SELECTION_TOOL:
|
||||||
|
toolName = "pcbnew.InteractiveSelection";
|
||||||
|
activateTool = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do nothing if the legacy view is active
|
||||||
|
if( activateTool && m_editFrame->IsGalCanvasActive() )
|
||||||
|
m_toolMgr->InvokeTool( toolName );
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* 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 <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <tool/tool_event.h>
|
||||||
|
#include <tool/tool_action.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct FlagString
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
|
std::string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const std::string flag2string( int aFlag, const FlagString* aExps )
|
||||||
|
{
|
||||||
|
std::string rv;
|
||||||
|
|
||||||
|
for( int i = 0; aExps[i].str.length(); i++ )
|
||||||
|
{
|
||||||
|
if( aExps[i].flag & aFlag )
|
||||||
|
rv += aExps[i].str + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const
|
||||||
|
{
|
||||||
|
return Matches( aAction->MakeEvent() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string TOOL_EVENT::Format() const
|
||||||
|
{
|
||||||
|
std::string ev;
|
||||||
|
|
||||||
|
const FlagString categories[] =
|
||||||
|
{
|
||||||
|
{ TC_MOUSE, "mouse" },
|
||||||
|
{ TC_KEYBOARD, "keyboard" },
|
||||||
|
{ TC_COMMAND, "command" },
|
||||||
|
{ TC_MESSAGE, "message" },
|
||||||
|
{ TC_VIEW, "view" },
|
||||||
|
{ 0, "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const FlagString actions[] =
|
||||||
|
{
|
||||||
|
{ TA_MOUSE_CLICK, "click" },
|
||||||
|
{ TA_MOUSE_UP, "button-up" },
|
||||||
|
{ TA_MOUSE_DOWN, "button-down" },
|
||||||
|
{ TA_MOUSE_DRAG, "drag" },
|
||||||
|
{ TA_MOUSE_MOTION, "motion" },
|
||||||
|
{ TA_MOUSE_WHEEL, "wheel" },
|
||||||
|
{ TA_KEY_UP, "key-up" },
|
||||||
|
{ TA_KEY_DOWN, "key-down" },
|
||||||
|
{ TA_VIEW_REFRESH, "view-refresh" },
|
||||||
|
{ TA_VIEW_ZOOM, "view-zoom" },
|
||||||
|
{ TA_VIEW_PAN, "view-pan" },
|
||||||
|
{ TA_VIEW_DIRTY, "view-dirty" },
|
||||||
|
{ TA_CHANGE_LAYER, "change-layer" },
|
||||||
|
{ TA_CANCEL_TOOL, "cancel-tool" },
|
||||||
|
{ TA_CONTEXT_MENU_UPDATE, "context-menu-update" },
|
||||||
|
{ TA_CONTEXT_MENU_CHOICE, "context-menu-choice" },
|
||||||
|
{ TA_ACTION, "action" },
|
||||||
|
{ 0, "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const FlagString buttons[] =
|
||||||
|
{
|
||||||
|
{ BUT_NONE, "none" },
|
||||||
|
{ BUT_LEFT, "left" },
|
||||||
|
{ BUT_RIGHT, "right" },
|
||||||
|
{ BUT_MIDDLE, "middle" },
|
||||||
|
{ 0, "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const FlagString modifiers[] =
|
||||||
|
{
|
||||||
|
{ MD_SHIFT, "shift" },
|
||||||
|
{ MD_CTRL, "ctrl" },
|
||||||
|
{ MD_ALT, "alt" },
|
||||||
|
{ 0, "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
ev = "category: ";
|
||||||
|
ev += flag2string( m_category, categories );
|
||||||
|
ev += " action: ";
|
||||||
|
ev += flag2string( m_actions, actions );
|
||||||
|
|
||||||
|
if( m_actions & TA_MOUSE )
|
||||||
|
{
|
||||||
|
ev += " btns: ";
|
||||||
|
ev += flag2string( m_mouseButtons, buttons );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_actions & TA_KEYBOARD )
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
sprintf( tmp, "key: %d", m_keyCode );
|
||||||
|
ev += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_actions & ( TA_MOUSE | TA_KEYBOARD ) )
|
||||||
|
{
|
||||||
|
ev += " mods: ";
|
||||||
|
ev += flag2string( m_modifiers, modifiers );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_commandId )
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
sprintf( tmp, "cmd-id: %d", *m_commandId );
|
||||||
|
ev += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_commandStr )
|
||||||
|
ev += "cmd-str: " + ( *m_commandStr );
|
||||||
|
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string TOOL_EVENT_LIST::Format() const
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
|
||||||
|
BOOST_FOREACH( TOOL_EVENT e, m_events )
|
||||||
|
s += e.Format() + " ";
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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 <string>
|
||||||
|
|
||||||
|
#include <tool/tool_event.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tool/tool_interactive.h>
|
||||||
|
#include <tool/context_menu.h>
|
||||||
|
|
||||||
|
TOOL_INTERACTIVE::TOOL_INTERACTIVE( TOOL_ID aId, const std::string& aName ) :
|
||||||
|
TOOL_BASE( INTERACTIVE, aId, aName )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_INTERACTIVE::TOOL_INTERACTIVE( const std::string& aName ) :
|
||||||
|
TOOL_BASE( INTERACTIVE, TOOL_MANAGER::MakeToolId( aName ), aName )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_INTERACTIVE::~TOOL_INTERACTIVE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OPT_TOOL_EVENT TOOL_INTERACTIVE::Wait( const TOOL_EVENT_LIST& aEventList )
|
||||||
|
{
|
||||||
|
return m_toolMgr->ScheduleWait( this, aEventList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_INTERACTIVE::goInternal( TOOL_STATE_FUNC& aState, const TOOL_EVENT_LIST& aConditions )
|
||||||
|
{
|
||||||
|
m_toolMgr->ScheduleNextState( this, aState, aConditions );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_INTERACTIVE::SetContextMenu( CONTEXT_MENU* aMenu, CONTEXT_MENU_TRIGGER aTrigger )
|
||||||
|
{
|
||||||
|
aMenu->setTool( this );
|
||||||
|
m_toolMgr->ScheduleContextMenu( this, aMenu, aTrigger );
|
||||||
|
}
|
|
@ -0,0 +1,513 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
* @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 <map>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/range/adaptor/map.hpp>
|
||||||
|
|
||||||
|
#include <wx/event.h>
|
||||||
|
|
||||||
|
#include <view/view.h>
|
||||||
|
|
||||||
|
#include <tool/tool_base.h>
|
||||||
|
#include <tool/tool_interactive.h>
|
||||||
|
#include <tool/tool_manager.h>
|
||||||
|
#include <tool/context_menu.h>
|
||||||
|
#include <tool/coroutine.h>
|
||||||
|
#include <tool/action_manager.h>
|
||||||
|
|
||||||
|
#include <wxPcbStruct.h>
|
||||||
|
#include <class_drawpanel_gal.h>
|
||||||
|
|
||||||
|
using boost::optional;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/// Struct describing the current execution state of a TOOL
|
||||||
|
struct TOOL_MANAGER::TOOL_STATE
|
||||||
|
{
|
||||||
|
/// The tool itself
|
||||||
|
TOOL_BASE* theTool;
|
||||||
|
|
||||||
|
/// Is the tool active (pending execution) or disabled at the moment
|
||||||
|
bool idle;
|
||||||
|
|
||||||
|
/// Flag defining if the tool is waiting for any event (i.e. if it
|
||||||
|
/// issued a Wait() call).
|
||||||
|
bool pendingWait;
|
||||||
|
|
||||||
|
/// Is there a context menu being displayed
|
||||||
|
bool pendingContextMenu;
|
||||||
|
|
||||||
|
/// Context menu currently used by the tool
|
||||||
|
CONTEXT_MENU* contextMenu;
|
||||||
|
|
||||||
|
/// Defines when the context menu is opened
|
||||||
|
CONTEXT_MENU_TRIGGER contextMenuTrigger;
|
||||||
|
|
||||||
|
/// Tool execution context
|
||||||
|
COROUTINE<int, TOOL_EVENT&>* cofunc;
|
||||||
|
|
||||||
|
/// The event that triggered the execution/wakeup of the tool after Wait() call
|
||||||
|
TOOL_EVENT wakeupEvent;
|
||||||
|
|
||||||
|
/// List of events the tool is currently waiting for
|
||||||
|
TOOL_EVENT_LIST waitEvents;
|
||||||
|
|
||||||
|
/// List of possible transitions (ie. association of events and state handlers that are executed
|
||||||
|
/// upon the event reception
|
||||||
|
std::vector<TRANSITION> transitions;
|
||||||
|
|
||||||
|
bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const
|
||||||
|
{
|
||||||
|
return aRhs.theTool == this->theTool;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=( const TOOL_MANAGER::TOOL_STATE& aRhs ) const
|
||||||
|
{
|
||||||
|
return aRhs.theTool != this->theTool;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_MANAGER::TOOL_MANAGER() :
|
||||||
|
m_model( NULL ), m_view( NULL )
|
||||||
|
{
|
||||||
|
m_actionMgr = new ACTION_MANAGER( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_MANAGER::~TOOL_MANAGER()
|
||||||
|
{
|
||||||
|
std::map<TOOL_BASE*, TOOL_STATE*>::iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_toolState.begin(), it_end = m_toolState.end(); it != it_end; ++it )
|
||||||
|
{
|
||||||
|
delete it->second->cofunc; // delete cofunction
|
||||||
|
delete it->second; // delete TOOL_STATE
|
||||||
|
delete it->first; // delete the tool itself
|
||||||
|
}
|
||||||
|
|
||||||
|
delete m_actionMgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = new TOOL_STATE;
|
||||||
|
|
||||||
|
st->theTool = aTool;
|
||||||
|
st->idle = true;
|
||||||
|
st->pendingWait = false;
|
||||||
|
st->pendingContextMenu = false;
|
||||||
|
st->cofunc = NULL;
|
||||||
|
st->contextMenuTrigger = CMENU_OFF;
|
||||||
|
|
||||||
|
m_toolState[aTool] = st;
|
||||||
|
m_toolNameIndex[aTool->GetName()] = st;
|
||||||
|
m_toolIdIndex[aTool->GetId()] = st;
|
||||||
|
|
||||||
|
aTool->m_toolMgr = this;
|
||||||
|
|
||||||
|
if( aTool->GetType() == INTERACTIVE )
|
||||||
|
{
|
||||||
|
bool initState = static_cast<TOOL_INTERACTIVE*>( aTool )->Init();
|
||||||
|
|
||||||
|
if( !initState )
|
||||||
|
{
|
||||||
|
wxLogError( wxT( "Initialization of the %s tool failed" ), aTool->GetName().c_str() );
|
||||||
|
|
||||||
|
// Unregister the tool
|
||||||
|
m_toolState.erase( aTool );
|
||||||
|
m_toolNameIndex.erase( aTool->GetName() );
|
||||||
|
m_toolIdIndex.erase( aTool->GetId() );
|
||||||
|
|
||||||
|
delete st;
|
||||||
|
delete aTool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::InvokeTool( TOOL_ID aToolId )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolId );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == INTERACTIVE )
|
||||||
|
return invokeTool( tool );
|
||||||
|
|
||||||
|
return false; // there is no tool with the given id
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::InvokeTool( const std::string& aToolName )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolName );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == INTERACTIVE )
|
||||||
|
return invokeTool( tool );
|
||||||
|
|
||||||
|
return false; // there is no tool with the given name
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::RegisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
m_actionMgr->RegisterAction( aAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::UnregisterAction( TOOL_ACTION* aAction )
|
||||||
|
{
|
||||||
|
m_actionMgr->UnregisterAction( aAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
wxASSERT( aTool != NULL );
|
||||||
|
|
||||||
|
TOOL_EVENT evt( TC_COMMAND, TA_ACTION, aTool->GetName() );
|
||||||
|
ProcessEvent( evt );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( TOOL_ID aToolId )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolId );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == INTERACTIVE )
|
||||||
|
return runTool( tool );
|
||||||
|
|
||||||
|
return false; // there is no tool with the given id
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( const std::string& aToolName )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = FindTool( aToolName );
|
||||||
|
|
||||||
|
if( tool && tool->GetType() == INTERACTIVE )
|
||||||
|
return runTool( tool );
|
||||||
|
|
||||||
|
return false; // there is no tool with the given name
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::runTool( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
wxASSERT( aTool != NULL );
|
||||||
|
|
||||||
|
if( !isRegistered( aTool ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TOOL_STATE* state = m_toolState[aTool];
|
||||||
|
|
||||||
|
// If the tool is already active, do not invoke it again
|
||||||
|
if( state->idle == false )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
state->idle = false;
|
||||||
|
|
||||||
|
static_cast<TOOL_INTERACTIVE*>( aTool )->Reset();
|
||||||
|
|
||||||
|
// Add the tool on the front of the processing queue (it gets events first)
|
||||||
|
m_activeTools.push_front( aTool->GetId() );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_BASE* TOOL_MANAGER::FindTool( int aId ) const
|
||||||
|
{
|
||||||
|
std::map<TOOL_ID, TOOL_STATE*>::const_iterator it = m_toolIdIndex.find( aId );
|
||||||
|
|
||||||
|
if( it != m_toolIdIndex.end() )
|
||||||
|
return it->second->theTool;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_BASE* TOOL_MANAGER::FindTool( const std::string& aName ) const
|
||||||
|
{
|
||||||
|
std::map<std::string, TOOL_STATE*>::const_iterator it = m_toolNameIndex.find( aName );
|
||||||
|
|
||||||
|
if( it != m_toolNameIndex.end() )
|
||||||
|
return it->second->theTool;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::ScheduleNextState( TOOL_BASE* aTool, TOOL_STATE_FUNC& aHandler,
|
||||||
|
const TOOL_EVENT_LIST& aConditions )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = m_toolState[aTool];
|
||||||
|
|
||||||
|
st->transitions.push_back( TRANSITION( aConditions, aHandler ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool,
|
||||||
|
const TOOL_EVENT_LIST& aConditions )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = m_toolState[aTool];
|
||||||
|
|
||||||
|
// indicate to the manager that we are going to sleep and we shall be
|
||||||
|
// woken up when an event matching aConditions arrive
|
||||||
|
st->pendingWait = true;
|
||||||
|
st->waitEvents = aConditions;
|
||||||
|
|
||||||
|
// switch context back to event dispatcher loop
|
||||||
|
st->cofunc->Yield();
|
||||||
|
|
||||||
|
return st->wakeupEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
// iterate over all registered tools
|
||||||
|
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = m_toolIdIndex[toolId];
|
||||||
|
|
||||||
|
// the tool state handler is waiting for events (i.e. called Wait() method)
|
||||||
|
if( st->pendingWait )
|
||||||
|
{
|
||||||
|
if( st->waitEvents.Matches( aEvent ) )
|
||||||
|
{
|
||||||
|
// By default, already processed events are not passed further
|
||||||
|
m_passEvent = false;
|
||||||
|
|
||||||
|
// got matching event? clear wait list and wake up the coroutine
|
||||||
|
st->wakeupEvent = aEvent;
|
||||||
|
st->pendingWait = false;
|
||||||
|
st->waitEvents.clear();
|
||||||
|
|
||||||
|
if( st->cofunc && !st->cofunc->Resume() )
|
||||||
|
finishTool( st ); // The couroutine has finished
|
||||||
|
|
||||||
|
// If the tool did not request to propagate
|
||||||
|
// the event to other tools, we should stop it now
|
||||||
|
if( !m_passEvent )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
|
||||||
|
{
|
||||||
|
// the tool scheduled next state(s) by calling Go()
|
||||||
|
if( !st->pendingWait )
|
||||||
|
{
|
||||||
|
// no state handler in progress - check if there are any transitions (defined by
|
||||||
|
// Go() method that match the event.
|
||||||
|
if( st->transitions.size() )
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( TRANSITION tr, st->transitions )
|
||||||
|
{
|
||||||
|
if( tr.first.Matches( aEvent ) )
|
||||||
|
{
|
||||||
|
st->transitions.clear();
|
||||||
|
|
||||||
|
// no tool context allocated yet? Create one.
|
||||||
|
if( !st->cofunc )
|
||||||
|
st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second );
|
||||||
|
else
|
||||||
|
st->cofunc->SetEntry( tr.second );
|
||||||
|
|
||||||
|
// got match? Run the handler.
|
||||||
|
st->cofunc->Call( aEvent );
|
||||||
|
|
||||||
|
if( !st->cofunc->Running() )
|
||||||
|
finishTool( st ); // The couroutine has finished immediately?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
if( aEvent.Action() == TA_KEY_UP )
|
||||||
|
{
|
||||||
|
// Check if there is a hotkey associated
|
||||||
|
if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
|
||||||
|
return false; // hotkey event was handled so it does not go any further
|
||||||
|
}
|
||||||
|
else if( aEvent.Category() == TC_COMMAND ) // it may be a tool activation event
|
||||||
|
{
|
||||||
|
dispatchActivation( aEvent );
|
||||||
|
// do not return false, as the event has to go on to the destined tool
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
// Look for the tool that has the same name as parameter in the processed command TOOL_EVENT
|
||||||
|
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
|
||||||
|
{
|
||||||
|
if( st->theTool->GetName() == aEvent.m_commandStr )
|
||||||
|
{
|
||||||
|
runTool( st->theTool );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
|
||||||
|
{
|
||||||
|
// Find the tool to be deactivated
|
||||||
|
std::deque<TOOL_ID>::iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_activeTools.begin(), it_end = m_activeTools.end(); it != it_end; ++it )
|
||||||
|
{
|
||||||
|
if( aState == m_toolIdIndex[*it] )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( it != m_activeTools.end() )
|
||||||
|
m_activeTools.erase( it );
|
||||||
|
else
|
||||||
|
wxLogWarning( wxT( "Tried to finish inactive tool" ) );
|
||||||
|
|
||||||
|
aState->idle = true;
|
||||||
|
delete aState->cofunc;
|
||||||
|
aState->cofunc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
|
||||||
|
{
|
||||||
|
// wxLogDebug( "event: %s", aEvent.Format().c_str() );
|
||||||
|
|
||||||
|
// Early dispatch of events destined for the TOOL_MANAGER
|
||||||
|
if( !dispatchStandardEvents( aEvent ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dispatchInternal( aEvent );
|
||||||
|
|
||||||
|
// popup menu handling
|
||||||
|
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = m_toolIdIndex[toolId];
|
||||||
|
|
||||||
|
// the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
|
||||||
|
// or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
|
||||||
|
if( st->contextMenuTrigger != CMENU_OFF )
|
||||||
|
{
|
||||||
|
if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
st->pendingWait = true;
|
||||||
|
st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY );
|
||||||
|
|
||||||
|
if( st->contextMenuTrigger == CMENU_NOW )
|
||||||
|
st->contextMenuTrigger = CMENU_OFF;
|
||||||
|
|
||||||
|
boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
|
||||||
|
GetEditFrame()->PopupMenu( menu->GetMenu() );
|
||||||
|
|
||||||
|
//
|
||||||
|
TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE );
|
||||||
|
dispatchInternal( evt );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_view->IsDirty() )
|
||||||
|
{
|
||||||
|
PCB_EDIT_FRAME* f = static_cast<PCB_EDIT_FRAME*>( GetEditFrame() );
|
||||||
|
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
|
||||||
|
CONTEXT_MENU_TRIGGER aTrigger )
|
||||||
|
{
|
||||||
|
TOOL_STATE* st = m_toolState[aTool];
|
||||||
|
|
||||||
|
st->contextMenu = aMenu;
|
||||||
|
st->contextMenuTrigger = aTrigger;
|
||||||
|
|
||||||
|
// the tool wants the menu immediately? Preempt it and do so :)
|
||||||
|
if( aTrigger == CMENU_NOW )
|
||||||
|
st->cofunc->Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TOOL_ID TOOL_MANAGER::MakeToolId( const std::string& aToolName )
|
||||||
|
{
|
||||||
|
static int currentId;
|
||||||
|
|
||||||
|
return currentId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KIGFX::VIEW* aView,
|
||||||
|
KIGFX::VIEW_CONTROLS* aViewControls, wxWindow* aFrame )
|
||||||
|
{
|
||||||
|
m_model = aModel;
|
||||||
|
m_view = aView;
|
||||||
|
m_viewControls = aViewControls;
|
||||||
|
m_editFrame = aFrame;
|
||||||
|
|
||||||
|
// Reset state of the registered tools
|
||||||
|
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
|
||||||
|
{
|
||||||
|
TOOL_BASE* tool = m_toolIdIndex[toolId]->theTool;
|
||||||
|
|
||||||
|
if( tool->GetType() == INTERACTIVE )
|
||||||
|
static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TOOL_MANAGER::isActive( TOOL_BASE* aTool )
|
||||||
|
{
|
||||||
|
if( !isRegistered( aTool ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !m_toolState[aTool]->idle;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file view_group.cpp
|
||||||
|
* @brief VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
|
||||||
|
* VIEW_GROUP does not take over ownership of the held items. The main purpose of this class is
|
||||||
|
* to group items and draw them on a single layer (in particular the overlay).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <view/view_group.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
#include <painter.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <layers_id_colors_and_visibility.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
VIEW_GROUP::VIEW_GROUP( VIEW* aView ) :
|
||||||
|
m_layer( ITEM_GAL_LAYER( GP_OVERLAY ) )
|
||||||
|
{
|
||||||
|
m_view = aView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VIEW_GROUP::~VIEW_GROUP()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::Add( VIEW_ITEM* aItem )
|
||||||
|
{
|
||||||
|
m_items.insert( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::Remove( VIEW_ITEM* aItem )
|
||||||
|
{
|
||||||
|
m_items.erase( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::Clear()
|
||||||
|
{
|
||||||
|
m_items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int VIEW_GROUP::GetSize() const
|
||||||
|
{
|
||||||
|
return m_items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BOX2I VIEW_GROUP::ViewBBox() const
|
||||||
|
{
|
||||||
|
BOX2I maxBox;
|
||||||
|
|
||||||
|
maxBox.SetMaximum();
|
||||||
|
return maxBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::ViewDraw( int aLayer, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
PAINTER* painter = m_view->GetPainter();
|
||||||
|
|
||||||
|
// Draw all items immediately (without caching)
|
||||||
|
BOOST_FOREACH( VIEW_ITEM* item, m_items )
|
||||||
|
{
|
||||||
|
aGal->PushDepth();
|
||||||
|
|
||||||
|
int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
|
||||||
|
item->ViewGetLayers( layers, layers_count );
|
||||||
|
m_view->SortLayers( layers, layers_count );
|
||||||
|
|
||||||
|
for( int i = 0; i < layers_count; i++ )
|
||||||
|
{
|
||||||
|
if( m_view->IsCached( layers[i] ) && m_view->IsLayerVisible( layers[i] ) )
|
||||||
|
{
|
||||||
|
aGal->AdvanceDepth();
|
||||||
|
|
||||||
|
if( !painter->Draw( item, layers[i] ) )
|
||||||
|
item->ViewDraw( layers[i], aGal ); // Alternative drawing method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aGal->PopDepth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||||
|
{
|
||||||
|
// Everything is displayed on a single layer
|
||||||
|
aLayers[0] = m_layer;
|
||||||
|
aCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::FreeItems()
|
||||||
|
{
|
||||||
|
BOOST_FOREACH( VIEW_ITEM* item, m_items )
|
||||||
|
{
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
m_items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::ItemsSetVisibility( bool aVisible )
|
||||||
|
{
|
||||||
|
std::set<VIEW_ITEM*>::const_iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||||
|
(*it)->ViewSetVisible( aVisible );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags )
|
||||||
|
{
|
||||||
|
std::set<VIEW_ITEM*>::const_iterator it, it_end;
|
||||||
|
|
||||||
|
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||||
|
(*it)->ViewUpdate( aFlags );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_GROUP::updateBbox()
|
||||||
|
{
|
||||||
|
// Save the used VIEW, as it used nulled during Remove()
|
||||||
|
VIEW* view = m_view;
|
||||||
|
|
||||||
|
// Reinsert the group, so the bounding box can be updated
|
||||||
|
view->Remove( this );
|
||||||
|
view->Add( this );
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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_visible != aIsVisible )
|
||||||
|
{
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_visible = aIsVisible;
|
||||||
|
|
||||||
|
// update only if the visibility has really changed
|
||||||
|
if( update )
|
||||||
|
{
|
||||||
|
ViewUpdate( APPEARANCE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_ITEM::ViewUpdate( int aUpdateFlags )
|
||||||
|
{
|
||||||
|
if( !m_view )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_view->invalidateItem( this, aUpdateFlags );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_ITEM::ViewRelease()
|
||||||
|
{
|
||||||
|
if( m_view && m_view->IsDynamic() )
|
||||||
|
{
|
||||||
|
m_view->Remove( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const
|
||||||
|
{
|
||||||
|
int* layersPtr = aLayers;
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < m_layers.size(); ++i )
|
||||||
|
{
|
||||||
|
if( m_layers[i] )
|
||||||
|
*layersPtr++ = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
aCount = m_layers.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int VIEW_ITEM::getGroup( int aLayer ) const
|
||||||
|
{
|
||||||
|
for( int i = 0; i < m_groupsSize; ++i )
|
||||||
|
{
|
||||||
|
if( m_groups[i].first == aLayer )
|
||||||
|
return m_groups[i].second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<int> VIEW_ITEM::getAllGroups() const
|
||||||
|
{
|
||||||
|
std::vector<int> groups( m_groupsSize );
|
||||||
|
|
||||||
|
for( int i = 0; i < m_groupsSize; ++i )
|
||||||
|
{
|
||||||
|
groups[i] = m_groups[i].second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_ITEM::setGroup( int aLayer, int aId )
|
||||||
|
{
|
||||||
|
// Look if there is already an entry for the layer
|
||||||
|
for( int i = 0; i < m_groupsSize; ++i )
|
||||||
|
{
|
||||||
|
if( m_groups[i].first == aLayer )
|
||||||
|
{
|
||||||
|
m_groups[i].second = aId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there was no entry for the given layer - create one
|
||||||
|
GroupPair* newGroups = new GroupPair[m_groupsSize + 1];
|
||||||
|
|
||||||
|
if( m_groupsSize > 0 )
|
||||||
|
{
|
||||||
|
std::copy( m_groups, m_groups + m_groupsSize, newGroups );
|
||||||
|
delete[] m_groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_groups = newGroups;
|
||||||
|
newGroups[m_groupsSize++] = GroupPair( aLayer, aId );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_ITEM::deleteGroups()
|
||||||
|
{
|
||||||
|
delete[] m_groups;
|
||||||
|
m_groups = NULL;
|
||||||
|
m_groupsSize = 0;
|
||||||
|
}
|
|
@ -0,0 +1,311 @@
|
||||||
|
/*
|
||||||
|
* 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 <view/view.h>
|
||||||
|
#include <view/wx_view_controls.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <tool/tool_dispatcher.h>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
|
||||||
|
|
||||||
|
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
|
||||||
|
VIEW_CONTROLS( aView ),
|
||||||
|
m_state( IDLE ),
|
||||||
|
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_MIDDLE_UP,
|
||||||
|
wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), NULL, this );
|
||||||
|
m_parentPanel->Connect( wxEVT_MIDDLE_DOWN,
|
||||||
|
wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), NULL, this );
|
||||||
|
m_parentPanel->Connect( wxEVT_LEFT_UP,
|
||||||
|
wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), NULL, this );
|
||||||
|
m_parentPanel->Connect( wxEVT_LEFT_DOWN,
|
||||||
|
wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), NULL, this );
|
||||||
|
#if defined _WIN32 || defined _WIN64
|
||||||
|
m_parentPanel->Connect( wxEVT_ENTER_WINDOW,
|
||||||
|
wxMouseEventHandler( WX_VIEW_CONTROLS::onEnter ), NULL, this );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_panTimer.SetOwner( this );
|
||||||
|
this->Connect( wxEVT_TIMER,
|
||||||
|
wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), NULL, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VIEW_CONTROLS::ShowCursor( bool aEnabled )
|
||||||
|
{
|
||||||
|
m_view->GetGAL()->SetCursorEnabled( aEnabled );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_mousePosition.x = aEvent.GetX();
|
||||||
|
m_mousePosition.y = aEvent.GetY();
|
||||||
|
|
||||||
|
if( m_forceCursorPosition )
|
||||||
|
m_cursorPosition = m_view->ToScreen( m_forcedPosition );
|
||||||
|
else if( m_snappingEnabled )
|
||||||
|
m_cursorPosition = m_view->GetGAL()->GetGridPoint( m_mousePosition );
|
||||||
|
else
|
||||||
|
m_cursorPosition = m_mousePosition;
|
||||||
|
|
||||||
|
bool isAutoPanning = false;
|
||||||
|
|
||||||
|
if( m_autoPanEnabled )
|
||||||
|
{
|
||||||
|
isAutoPanning = handleAutoPanning( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !isAutoPanning && aEvent.Dragging() )
|
||||||
|
{
|
||||||
|
if( m_state == DRAG_PANNING )
|
||||||
|
{
|
||||||
|
VECTOR2D d = m_dragStartPoint - m_mousePosition;
|
||||||
|
VECTOR2D delta = m_view->ToWorld( d, false );
|
||||||
|
|
||||||
|
m_view->SetCenter( m_lookStartPoint + delta );
|
||||||
|
aEvent.StopPropagation();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
const double wheelPanSpeed = 0.001;
|
||||||
|
|
||||||
|
if( aEvent.ControlDown() || aEvent.ShiftDown() )
|
||||||
|
{
|
||||||
|
// Scrolling
|
||||||
|
VECTOR2D scrollVec = m_view->ToWorld( m_view->GetScreenPixelSize() *
|
||||||
|
( (double) aEvent.GetWheelRotation() * wheelPanSpeed ), false );
|
||||||
|
double scrollSpeed;
|
||||||
|
|
||||||
|
if( abs( scrollVec.x ) > abs( scrollVec.y ) )
|
||||||
|
scrollSpeed = scrollVec.x;
|
||||||
|
else
|
||||||
|
scrollSpeed = scrollVec.y;
|
||||||
|
|
||||||
|
VECTOR2D delta( aEvent.ControlDown() ? -scrollSpeed : 0.0,
|
||||||
|
aEvent.ShiftDown() ? -scrollSpeed : 0.0 );
|
||||||
|
|
||||||
|
m_view->SetCenter( m_view->GetCenter() + delta );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Zooming
|
||||||
|
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 = ( aEvent.GetWheelRotation() > 0.0 ) ? 2.05 - timeDiff / 500 :
|
||||||
|
1.0 / ( 2.05 - timeDiff / 500 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zoomScale = ( aEvent.GetWheelRotation() > 0.0 ) ? 1.05 : 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
|
||||||
|
m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
|
||||||
|
}
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
switch( m_state )
|
||||||
|
{
|
||||||
|
case IDLE:
|
||||||
|
case AUTO_PANNING:
|
||||||
|
if( aEvent.MiddleDown() )
|
||||||
|
{
|
||||||
|
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
|
||||||
|
m_lookStartPoint = m_view->GetCenter();
|
||||||
|
m_state = DRAG_PANNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aEvent.LeftUp() )
|
||||||
|
{
|
||||||
|
m_state = IDLE; // Stop autopanning when user release left mouse button
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRAG_PANNING:
|
||||||
|
if( aEvent.MiddleUp() )
|
||||||
|
{
|
||||||
|
m_state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_parentPanel->SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
|
||||||
|
{
|
||||||
|
switch( m_state )
|
||||||
|
{
|
||||||
|
case AUTO_PANNING:
|
||||||
|
{
|
||||||
|
double borderSize = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x,
|
||||||
|
m_autoPanMargin * m_view->GetScreenPixelSize().y );
|
||||||
|
|
||||||
|
VECTOR2D dir( m_panDirection );
|
||||||
|
|
||||||
|
if( dir.EuclideanNorm() > borderSize )
|
||||||
|
dir = dir.Resize( borderSize );
|
||||||
|
|
||||||
|
dir = m_view->ToWorld( dir, false );
|
||||||
|
m_view->SetCenter( m_view->GetCenter() + dir * m_autoPanSpeed );
|
||||||
|
|
||||||
|
// Notify tools that the cursor position has changed in the world coordinates
|
||||||
|
wxCommandEvent moveEvent( EVT_REFRESH_MOUSE );
|
||||||
|
wxPostEvent( m_parentPanel, moveEvent );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDLE: // Just remove unnecessary warnings
|
||||||
|
case DRAG_PANNING:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
|
||||||
|
{
|
||||||
|
m_grabMouse = aEnabled;
|
||||||
|
|
||||||
|
if( aEnabled )
|
||||||
|
m_parentPanel->CaptureMouse();
|
||||||
|
else
|
||||||
|
m_parentPanel->ReleaseMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const VECTOR2D WX_VIEW_CONTROLS::GetMousePosition() const
|
||||||
|
{
|
||||||
|
wxPoint msp = wxGetMousePosition();
|
||||||
|
wxPoint winp = m_parentPanel->GetScreenPosition();
|
||||||
|
|
||||||
|
return VECTOR2D( msp.x - winp.x, msp.y - winp.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const VECTOR2D WX_VIEW_CONTROLS::GetCursorPosition() const
|
||||||
|
{
|
||||||
|
if( m_snappingEnabled )
|
||||||
|
return m_view->GetGAL()->GetGridPoint( GetMousePosition() );
|
||||||
|
else
|
||||||
|
return GetMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
VECTOR2D p( aEvent.GetX(), aEvent.GetY() );
|
||||||
|
|
||||||
|
// Compute areas where autopanning is active
|
||||||
|
double borderStart = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x,
|
||||||
|
m_autoPanMargin * m_view->GetScreenPixelSize().y );
|
||||||
|
double borderEndX = m_view->GetScreenPixelSize().x - borderStart;
|
||||||
|
double borderEndY = m_view->GetScreenPixelSize().y - borderStart;
|
||||||
|
|
||||||
|
m_panDirection = VECTOR2D();
|
||||||
|
|
||||||
|
if( p.x < borderStart )
|
||||||
|
m_panDirection.x = -( borderStart - p.x );
|
||||||
|
else if( p.x > borderEndX )
|
||||||
|
m_panDirection.x = ( p.x - borderEndX );
|
||||||
|
|
||||||
|
if( p.y < borderStart )
|
||||||
|
m_panDirection.y = -( borderStart - p.y );
|
||||||
|
else if( p.y > borderEndY )
|
||||||
|
m_panDirection.y = ( p.y - borderEndY );
|
||||||
|
|
||||||
|
bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
|
||||||
|
|
||||||
|
switch( m_state )
|
||||||
|
{
|
||||||
|
case AUTO_PANNING:
|
||||||
|
if( !borderHit )
|
||||||
|
{
|
||||||
|
m_panTimer.Stop();
|
||||||
|
m_state = IDLE;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDLE:
|
||||||
|
if( borderHit )
|
||||||
|
{
|
||||||
|
m_state = AUTO_PANNING;
|
||||||
|
m_panTimer.Start( (int) ( 1000.0 / 60.0 ) );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRAG_PANNING:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxASSERT_MSG( false, wxT( "This line should never be reached" ) );
|
||||||
|
return false; // Should not be reached, just avoid the compiler warnings..
|
||||||
|
}
|
|
@ -101,7 +101,7 @@ void EDA_DRAW_FRAME::DrawWorkSheet( wxDC* aDC, BASE_SCREEN* aScreen, int aLineWi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString EDA_DRAW_FRAME::GetScreenDesc()
|
wxString EDA_DRAW_FRAME::GetScreenDesc() const
|
||||||
{
|
{
|
||||||
// Virtual function. In basic class, returns
|
// Virtual function. In basic class, returns
|
||||||
// an empty string.
|
// an empty string.
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file worksheet_viewitem.cpp
|
||||||
|
* @brief Class that handles properties and drawing of worksheet layout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <worksheet_viewitem.h>
|
||||||
|
#include <worksheet_shape_builder.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <painter.h>
|
||||||
|
#include <layers_id_colors_and_visibility.h>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
WORKSHEET_VIEWITEM::WORKSHEET_VIEWITEM( const std::string& aFileName, const std::string& aSheetName,
|
||||||
|
const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ) :
|
||||||
|
EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type
|
||||||
|
m_fileName( aFileName ), m_sheetName( aSheetName ),
|
||||||
|
m_titleBlock( aTitleBlock ), m_pageInfo( aPageInfo ), m_sheetNumber( 1 ), m_sheetCount( 1 ) {}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::SetPageInfo( const PAGE_INFO* aPageInfo )
|
||||||
|
{
|
||||||
|
m_pageInfo = aPageInfo;
|
||||||
|
ViewUpdate( GEOMETRY );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock )
|
||||||
|
{
|
||||||
|
m_titleBlock = aTitleBlock;
|
||||||
|
ViewUpdate( GEOMETRY );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BOX2I WORKSHEET_VIEWITEM::ViewBBox() const
|
||||||
|
{
|
||||||
|
BOX2I bbox;
|
||||||
|
|
||||||
|
if( m_pageInfo != NULL )
|
||||||
|
{
|
||||||
|
bbox.SetOrigin( VECTOR2I( 0, 0 ) );
|
||||||
|
bbox.SetEnd( VECTOR2I( m_pageInfo->GetWidthMils() * 25400,
|
||||||
|
m_pageInfo->GetHeightMils() * 25400 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bbox.SetMaximum();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings();
|
||||||
|
wxString fileName( m_fileName.c_str(), wxConvUTF8 );
|
||||||
|
wxString sheetName( m_sheetName.c_str(), wxConvUTF8 );
|
||||||
|
WS_DRAW_ITEM_LIST drawList;
|
||||||
|
|
||||||
|
drawList.SetPenSize( settings->GetWorksheetLineWidth() );
|
||||||
|
// Sorry, but I don't get this multi #ifdef from include/convert_to_biu.h, so here goes a magic
|
||||||
|
// number. IU_PER_MILS should be 25400 (as in a different compilation unit), but somehow
|
||||||
|
// it equals 1 in this case..
|
||||||
|
drawList.SetMilsToIUfactor( 25400 /* IU_PER_MILS */ );
|
||||||
|
drawList.SetSheetNumber( m_sheetNumber );
|
||||||
|
drawList.SetSheetCount( m_sheetCount );
|
||||||
|
drawList.SetFileName( fileName );
|
||||||
|
drawList.SetSheetName( sheetName );
|
||||||
|
|
||||||
|
COLOR4D color = settings->GetColor( this, aLayer );
|
||||||
|
EDA_COLOR_T edaColor = ColorFindNearest( color.r * 255, color.g * 255, color.b * 255 );
|
||||||
|
drawList.BuildWorkSheetGraphicList( *m_pageInfo, *m_titleBlock, edaColor, edaColor );
|
||||||
|
|
||||||
|
// Draw all the components that make the page layout
|
||||||
|
WS_DRAW_ITEM_BASE* item = drawList.GetFirst();
|
||||||
|
while( item )
|
||||||
|
{
|
||||||
|
switch( item->GetType() )
|
||||||
|
{
|
||||||
|
case WS_DRAW_ITEM_BASE::wsg_line:
|
||||||
|
draw( static_cast<const WS_DRAW_ITEM_LINE*>( item ), aGal );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WS_DRAW_ITEM_BASE::wsg_rect:
|
||||||
|
draw( static_cast<const WS_DRAW_ITEM_RECT*>( item ), aGal );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WS_DRAW_ITEM_BASE::wsg_poly:
|
||||||
|
draw( static_cast<const WS_DRAW_ITEM_POLYGON*>( item ), aGal );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WS_DRAW_ITEM_BASE::wsg_text:
|
||||||
|
draw( static_cast<const WS_DRAW_ITEM_TEXT*>( item ), aGal );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = drawList.GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw gray line that outlines the sheet size
|
||||||
|
drawBorder( aGal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||||
|
{
|
||||||
|
aCount = 1;
|
||||||
|
aLayers[0] = ITEM_GAL_LAYER( WORKSHEET );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_LINE* aItem, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
aGal->SetIsStroke( true );
|
||||||
|
aGal->SetIsFill( false );
|
||||||
|
aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) );
|
||||||
|
aGal->SetLineWidth( aItem->GetPenWidth() );
|
||||||
|
aGal->DrawLine( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_RECT* aItem, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
aGal->SetIsStroke( true );
|
||||||
|
aGal->SetIsFill( false );
|
||||||
|
aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) );
|
||||||
|
aGal->SetLineWidth( aItem->GetPenWidth() );
|
||||||
|
aGal->DrawRectangle( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_POLYGON* aItem, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
std::deque<VECTOR2D> corners;
|
||||||
|
BOOST_FOREACH( wxPoint point, aItem->m_Corners )
|
||||||
|
{
|
||||||
|
corners.push_back( VECTOR2D( point ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aItem->IsFilled() )
|
||||||
|
{
|
||||||
|
aGal->SetFillColor( COLOR4D( aItem->GetColor() ) );
|
||||||
|
aGal->SetIsFill( true );
|
||||||
|
aGal->SetIsStroke( false );
|
||||||
|
aGal->DrawPolygon( corners );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) );
|
||||||
|
aGal->SetIsFill( false );
|
||||||
|
aGal->SetIsStroke( true );
|
||||||
|
aGal->SetLineWidth( aItem->GetPenWidth() );
|
||||||
|
aGal->DrawPolyline( corners );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const
|
||||||
|
{
|
||||||
|
VECTOR2D position( aItem->GetTextPosition().x, aItem->GetTextPosition().y );
|
||||||
|
|
||||||
|
aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) );
|
||||||
|
aGal->SetLineWidth( aItem->GetThickness() );
|
||||||
|
aGal->SetTextAttributes( aItem );
|
||||||
|
aGal->StrokeText( std::string( aItem->GetText().mb_str() ), position, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WORKSHEET_VIEWITEM::drawBorder( GAL* aGal ) const
|
||||||
|
{
|
||||||
|
VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
|
||||||
|
VECTOR2D end = VECTOR2D( m_pageInfo->GetWidthMils() * 25400,
|
||||||
|
m_pageInfo->GetHeightMils() * 25400 );
|
||||||
|
|
||||||
|
aGal->SetIsStroke( true );
|
||||||
|
aGal->SetIsFill( false );
|
||||||
|
aGal->DrawRectangle( origin, end );
|
||||||
|
}
|
|
@ -33,6 +33,9 @@
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <id.h>
|
#include <id.h>
|
||||||
#include <class_drawpanel.h>
|
#include <class_drawpanel.h>
|
||||||
|
#include <class_drawpanel_gal.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <view/view.h>
|
||||||
#include <class_base_screen.h>
|
#include <class_base_screen.h>
|
||||||
#include <wxstruct.h>
|
#include <wxstruct.h>
|
||||||
#include <kicad_device_context.h>
|
#include <kicad_device_context.h>
|
||||||
|
@ -41,7 +44,6 @@
|
||||||
#include <base_units.h>
|
#include <base_units.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
|
void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
|
||||||
{
|
{
|
||||||
AdjustScrollBars( aCenterPoint );
|
AdjustScrollBars( aCenterPoint );
|
||||||
|
@ -82,7 +84,8 @@ void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
|
||||||
if( screen->m_FirstRedraw )
|
if( screen->m_FirstRedraw )
|
||||||
SetCrossHairPosition( GetScrollCenterPosition() );
|
SetCrossHairPosition( GetScrollCenterPosition() );
|
||||||
|
|
||||||
RedrawScreen( GetScrollCenterPosition(), aWarpPointer );
|
if( !m_galCanvasActive )
|
||||||
|
RedrawScreen( GetScrollCenterPosition(), aWarpPointer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,6 +194,20 @@ void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event )
|
||||||
RedrawScreen( center, true );
|
RedrawScreen( center, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( m_galCanvasActive )
|
||||||
|
{
|
||||||
|
// Apply computed view settings to GAL
|
||||||
|
KIGFX::VIEW* view = m_galCanvas->GetView();
|
||||||
|
KIGFX::GAL* gal = m_galCanvas->GetGAL();
|
||||||
|
|
||||||
|
double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
|
||||||
|
double zoom = 1.0 / ( zoomFactor * GetZoom() );
|
||||||
|
|
||||||
|
view->SetScale( zoom );
|
||||||
|
view->SetCenter( VECTOR2D( center ) );
|
||||||
|
m_galCanvas->Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,11 +101,27 @@ target_link_libraries( cvpcb
|
||||||
common
|
common
|
||||||
bitmaps
|
bitmaps
|
||||||
polygon
|
polygon
|
||||||
|
gal
|
||||||
${wxWidgets_LIBRARIES}
|
${wxWidgets_LIBRARIES}
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${GDI_PLUS_LIBRARIES}
|
${GDI_PLUS_LIBRARIES}
|
||||||
|
${GLEW_LIBRARIES}
|
||||||
|
${CAIRO_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Only for win32 cross compilation using MXE
|
||||||
|
if(WIN32 AND MSYS)
|
||||||
|
target_link_libraries(cvpcb
|
||||||
|
opengl32
|
||||||
|
glu32
|
||||||
|
pixman-1
|
||||||
|
fontconfig
|
||||||
|
freetype
|
||||||
|
bz2
|
||||||
|
)
|
||||||
|
endif(WIN32 AND MSYS)
|
||||||
|
|
||||||
|
|
||||||
if( BUILD_GITHUB_PLUGIN )
|
if( BUILD_GITHUB_PLUGIN )
|
||||||
target_link_libraries( cvpcb github_plugin )
|
target_link_libraries( cvpcb github_plugin )
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <appl_wxstruct.h>
|
#include <appl_wxstruct.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <class_drawpanel.h>
|
#include <class_drawpanel.h>
|
||||||
|
#include <class_drawpanel_gal.h>
|
||||||
#include <confirm.h>
|
#include <confirm.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <bitmaps.h>
|
#include <bitmaps.h>
|
||||||
|
@ -121,7 +122,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* parent,
|
||||||
EDA_PANEINFO mesg;
|
EDA_PANEINFO mesg;
|
||||||
mesg.MessageToolbarPane();
|
mesg.MessageToolbarPane();
|
||||||
|
|
||||||
|
m_galCanvas->Hide();
|
||||||
|
|
||||||
m_auimgr.AddPane( m_mainToolBar,
|
m_auimgr.AddPane( m_mainToolBar,
|
||||||
wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top(). Row( 0 ) );
|
wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top(). Row( 0 ) );
|
||||||
|
|
|
@ -281,7 +281,7 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
|
||||||
fpLibFileName.SetName( FP_LIB_TABLE::GetFileName() );
|
fpLibFileName.SetName( FP_LIB_TABLE::GetFileName() );
|
||||||
|
|
||||||
if( fpLibFileName.FileExists()
|
if( fpLibFileName.FileExists()
|
||||||
&& IsOK( this, _( "A footprint library table already exsist in this path.\n\nDo "
|
&& IsOK( this, _( "A footprint library table already exists in this path.\n\nDo "
|
||||||
"you want to overwrite it?" ) ) )
|
"you want to overwrite it?" ) ) )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -292,7 +292,7 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
|
||||||
{
|
{
|
||||||
DisplayError( this,
|
DisplayError( this,
|
||||||
wxString::Format( _( "An error occurred attempting to save the "
|
wxString::Format( _( "An error occurred attempting to save the "
|
||||||
"footpirnt library table <%s>\n\n%s" ),
|
"footprint library table <%s>\n\n%s" ),
|
||||||
GetChars( fpLibFileName.GetFullPath() ),
|
GetChars( fpLibFileName.GetFullPath() ),
|
||||||
GetChars( ioe.errorText ) ) );
|
GetChars( ioe.errorText ) ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( wxWindow
|
||||||
|
|
||||||
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& event )
|
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& event )
|
||||||
{
|
{
|
||||||
D( printf( "OnListItemDeselected()\n" ); )
|
DBG( printf( "OnListItemDeselected()\n" ); )
|
||||||
|
|
||||||
if( !m_skipCopyFromPanel )
|
if( !m_skipCopyFromPanel )
|
||||||
{
|
{
|
||||||
|
@ -202,7 +202,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemDeselected( wxListEvent& even
|
||||||
|
|
||||||
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event )
|
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnListItemSelected( wxListEvent& event )
|
||||||
{
|
{
|
||||||
D( printf( "OnListItemSelected()\n" ); )
|
DBG( printf( "OnListItemSelected()\n" ); )
|
||||||
|
|
||||||
// remember the selected row, statically
|
// remember the selected row, statically
|
||||||
s_SelectedRow = event.GetIndex();
|
s_SelectedRow = event.GetIndex();
|
||||||
|
@ -460,7 +460,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::moveUpButtonHandler( wxCommandEvent& ev
|
||||||
// and in the fieldListCtrl
|
// and in the fieldListCtrl
|
||||||
SCH_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
|
SCH_FIELD tmp = m_FieldsBuf[fieldNdx - 1];
|
||||||
|
|
||||||
D( printf( "tmp.m_Text=\"%s\" tmp.m_Name=\"%s\"\n",
|
DBG( printf( "tmp.m_Text=\"%s\" tmp.m_Name=\"%s\"\n",
|
||||||
TO_UTF8( tmp.GetText() ), TO_UTF8( tmp.GetName( false ) ) ); )
|
TO_UTF8( tmp.GetText() ), TO_UTF8( tmp.GetName( false ) ) ); )
|
||||||
|
|
||||||
m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
|
m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
|
||||||
|
@ -880,12 +880,12 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
|
||||||
if( mirror == CMP_MIRROR_X )
|
if( mirror == CMP_MIRROR_X )
|
||||||
{
|
{
|
||||||
mirrorRadioBox->SetSelection( 1 );
|
mirrorRadioBox->SetSelection( 1 );
|
||||||
D( printf( "mirror=X,1\n" ); )
|
DBG( printf( "mirror=X,1\n" ); )
|
||||||
}
|
}
|
||||||
else if( mirror == CMP_MIRROR_Y )
|
else if( mirror == CMP_MIRROR_Y )
|
||||||
{
|
{
|
||||||
mirrorRadioBox->SetSelection( 2 );
|
mirrorRadioBox->SetSelection( 2 );
|
||||||
D( printf( "mirror=Y,2\n" ); )
|
DBG( printf( "mirror=Y,2\n" ); )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mirrorRadioBox->SetSelection( 0 );
|
mirrorRadioBox->SetSelection( 0 );
|
||||||
|
@ -905,7 +905,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
|
||||||
// Show the "Parts Locked" option?
|
// Show the "Parts Locked" option?
|
||||||
if( !m_LibEntry || !m_LibEntry->UnitsLocked() )
|
if( !m_LibEntry || !m_LibEntry->UnitsLocked() )
|
||||||
{
|
{
|
||||||
D( printf( "partsAreLocked->false\n" ); )
|
DBG( printf( "partsAreLocked->false\n" ); )
|
||||||
partsAreLockedLabel->Show( false );
|
partsAreLockedLabel->Show( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -480,7 +480,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
||||||
// fixed fields:
|
// fixed fields:
|
||||||
for( int i=0; i<MANDATORY_FIELDS; ++i )
|
for( int i=0; i<MANDATORY_FIELDS; ++i )
|
||||||
{
|
{
|
||||||
D( printf( "add fixed:%s\n", TO_UTF8( cmpFields[i].GetName() ) ); )
|
DBG( printf( "add fixed:%s\n", TO_UTF8( cmpFields[i].GetName() ) ); )
|
||||||
m_FieldsBuf.push_back( cmpFields[i] );
|
m_FieldsBuf.push_back( cmpFields[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
||||||
// values from the component will be set.
|
// values from the component will be set.
|
||||||
if( !libField )
|
if( !libField )
|
||||||
{
|
{
|
||||||
D( printf( "add template:%s\n", TO_UTF8( it->m_Name ) ); )
|
DBG( printf( "add template:%s\n", TO_UTF8( it->m_Name ) ); )
|
||||||
|
|
||||||
fld.SetName( it->m_Name );
|
fld.SetName( it->m_Name );
|
||||||
fld.SetText( it->m_Value ); // empty? ok too.
|
fld.SetText( it->m_Value ); // empty? ok too.
|
||||||
|
@ -517,7 +517,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D( printf( "match template:%s\n", TO_UTF8( libField->GetName() ) ); )
|
DBG( printf( "match template:%s\n", TO_UTF8( libField->GetName() ) ); )
|
||||||
fld = *libField; // copy values from component, m_Name too
|
fld = *libField; // copy values from component, m_Name too
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
||||||
|
|
||||||
if( !buf )
|
if( !buf )
|
||||||
{
|
{
|
||||||
D( printf( "add cmp:%s\n", TO_UTF8( cmp->GetName() ) ); )
|
DBG( printf( "add cmp:%s\n", TO_UTF8( cmp->GetName() ) ); )
|
||||||
m_FieldsBuf.push_back( *cmp );
|
m_FieldsBuf.push_back( *cmp );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,11 +731,11 @@ bool DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copyPanelToSelectedField()
|
||||||
if( field.GetId() >= MANDATORY_FIELDS )
|
if( field.GetId() >= MANDATORY_FIELDS )
|
||||||
{
|
{
|
||||||
wxString name = fieldNameTextCtrl->GetValue();
|
wxString name = fieldNameTextCtrl->GetValue();
|
||||||
D( printf("name:%s\n", TO_UTF8( name ) ); )
|
DBG( printf("name:%s\n", TO_UTF8( name ) ); )
|
||||||
field.SetName( name );
|
field.SetName( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
D( printf("setname:%s\n", TO_UTF8( field.GetName() ) ); )
|
DBG( printf("setname:%s\n", TO_UTF8( field.GetName() ) ); )
|
||||||
|
|
||||||
setRowItem( fieldNdx, field ); // update fieldListCtrl
|
setRowItem( fieldNdx, field ); // update fieldListCtrl
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
*/
|
*/
|
||||||
enum SchematicFindReplaceFlags
|
enum SchematicFindReplaceFlags
|
||||||
{
|
{
|
||||||
// The last wxFindReplaceFlag enum is wxFR_MATCHCASE.
|
// The last wxFindReplaceFlag enum is wxFR_MATCHCASE = 0x4.
|
||||||
|
|
||||||
/// Search the current sheet only.
|
/// Search the current sheet only.
|
||||||
FR_CURRENT_SHEET_ONLY = wxFR_MATCHCASE << 1,
|
FR_CURRENT_SHEET_ONLY = wxFR_MATCHCASE << 1,
|
||||||
|
|
|
@ -292,7 +292,7 @@ void SCH_EDIT_FRAME::OnSetOptions( wxCommandEvent& event )
|
||||||
|
|
||||||
for( unsigned i=0; i<tfnames.size(); ++i )
|
for( unsigned i=0; i<tfnames.size(); ++i )
|
||||||
{
|
{
|
||||||
D(printf("dlg.SetFieldName(%d, '%s')\n", i, TO_UTF8( tfnames[i].m_Name) );)
|
DBG(printf("dlg.SetFieldName(%d, '%s')\n", i, TO_UTF8( tfnames[i].m_Name) );)
|
||||||
|
|
||||||
dlg.SetFieldName( i, tfnames[i].m_Name );
|
dlg.SetFieldName( i, tfnames[i].m_Name );
|
||||||
}
|
}
|
||||||
|
@ -680,7 +680,7 @@ void SCH_EDIT_FRAME::LoadSettings()
|
||||||
catch( IO_ERROR& e )
|
catch( IO_ERROR& e )
|
||||||
{
|
{
|
||||||
// @todo show error msg
|
// @todo show error msg
|
||||||
D( printf( "templatefieldnames parsing error: '%s'\n",
|
DBG( printf( "templatefieldnames parsing error: '%s'\n",
|
||||||
TO_UTF8( e.errorText ) ); )
|
TO_UTF8( e.errorText ) ); )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,7 +751,7 @@ void SCH_EDIT_FRAME::SaveSettings()
|
||||||
|
|
||||||
m_TemplateFieldNames.Format( &sf, 0 );
|
m_TemplateFieldNames.Format( &sf, 0 );
|
||||||
|
|
||||||
D(printf("saving formatted template fieldnames:'%s'\n", sf.GetString().c_str() );)
|
DBG(printf("saving formatted template fieldnames:'%s'\n", sf.GetString().c_str() );)
|
||||||
|
|
||||||
wxString record = FROM_UTF8( sf.GetString().c_str() );
|
wxString record = FROM_UTF8( sf.GetString().c_str() );
|
||||||
record.Replace( wxT("\n"), wxT(""), true ); // strip all newlines
|
record.Replace( wxT("\n"), wxT(""), true ); // strip all newlines
|
||||||
|
|
|
@ -288,12 +288,11 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& aReference,
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
||||||
{
|
{
|
||||||
static wxPoint itemPosition; // the actual position of the matched item.
|
static wxPoint itemPosition; // the actual position of the matched item.
|
||||||
|
|
||||||
SCH_SHEET_LIST schematic;
|
SCH_SHEET_LIST schematic;
|
||||||
wxString msg;
|
wxString msg;
|
||||||
SCH_FIND_REPLACE_DATA searchCriteria;
|
SCH_FIND_REPLACE_DATA searchCriteria;
|
||||||
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
|
|
||||||
SCH_FIND_COLLECTOR_DATA data;
|
SCH_FIND_COLLECTOR_DATA data;
|
||||||
|
|
||||||
searchCriteria.SetFlags( aEvent.GetFlags() );
|
searchCriteria.SetFlags( aEvent.GetFlags() );
|
||||||
|
@ -326,6 +325,88 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
||||||
m_foundItems.UpdateIndex();
|
m_foundItems.UpdateIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFindReplaceView( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
|
||||||
|
{
|
||||||
|
SCH_ITEM* item;
|
||||||
|
SCH_SHEET_PATH* sheet;
|
||||||
|
SCH_SHEET_LIST schematic;
|
||||||
|
SCH_FIND_COLLECTOR_DATA data;
|
||||||
|
|
||||||
|
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
|
||||||
|
{
|
||||||
|
while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
|
||||||
|
{
|
||||||
|
SCH_ITEM* undoItem = data.GetParent();
|
||||||
|
|
||||||
|
// Don't save child items in undo list.
|
||||||
|
if( undoItem == NULL )
|
||||||
|
undoItem = item;
|
||||||
|
|
||||||
|
SetUndoItem( undoItem );
|
||||||
|
|
||||||
|
sheet = schematic.GetSheet( data.GetSheetPath() );
|
||||||
|
|
||||||
|
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
|
||||||
|
|
||||||
|
if( m_foundItems.ReplaceItem( sheet ) )
|
||||||
|
{
|
||||||
|
OnModify();
|
||||||
|
SaveUndoItemInUndoList( undoItem );
|
||||||
|
updateFindReplaceView( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_foundItems.IncrementIndex();
|
||||||
|
|
||||||
|
if( m_foundItems.PassedEnd() )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data );
|
||||||
|
|
||||||
|
wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) );
|
||||||
|
|
||||||
|
SCH_ITEM* undoItem = data.GetParent();
|
||||||
|
|
||||||
|
if( undoItem == NULL )
|
||||||
|
undoItem = item;
|
||||||
|
|
||||||
|
SetUndoItem( undoItem );
|
||||||
|
|
||||||
|
sheet = schematic.GetSheet( data.GetSheetPath() );
|
||||||
|
|
||||||
|
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) + data.GetSheetPath() );
|
||||||
|
|
||||||
|
if( m_foundItems.ReplaceItem( sheet ) )
|
||||||
|
{
|
||||||
|
OnModify();
|
||||||
|
SaveUndoItemInUndoList( undoItem );
|
||||||
|
updateFindReplaceView( aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_foundItems.IncrementIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the replace if we are at the end if the list. This prevents an infinite loop if
|
||||||
|
// wrap search is selected and all of the items have been replaced with a value that
|
||||||
|
// still satisfies the search criteria.
|
||||||
|
if( m_foundItems.PassedEnd() )
|
||||||
|
aEvent.SetFlags( aEvent.GetFlags() & ~FR_REPLACE_ITEM_FOUND );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCH_EDIT_FRAME::updateFindReplaceView( wxFindDialogEvent& aEvent )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
SCH_SHEET_LIST schematic;
|
||||||
|
SCH_FIND_COLLECTOR_DATA data;
|
||||||
|
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
|
||||||
|
|
||||||
if( m_foundItems.GetItem( data ) != NULL )
|
if( m_foundItems.GetItem( data ) != NULL )
|
||||||
{
|
{
|
||||||
wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() );
|
wxLogTrace( traceFindReplace, wxT( "Found " ) + m_foundItems.GetText() );
|
||||||
|
@ -335,13 +416,15 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
||||||
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
|
wxCHECK_RET( sheet != NULL, wxT( "Could not find sheet path " ) +
|
||||||
data.GetSheetPath() );
|
data.GetSheetPath() );
|
||||||
|
|
||||||
|
SCH_ITEM* item = (SCH_ITEM*)m_foundItems.GetItem( data );
|
||||||
|
|
||||||
// Make the item temporarily visible just in case it's hide flag is set. This
|
// Make the item temporarily visible just in case it's hide flag is set. This
|
||||||
// has no effect on objects that don't support hiding. If this is a close find
|
// has no effect on objects that don't support hiding. If this is a close find
|
||||||
// dialog event, clear the temporary visibility flag.
|
// dialog event, clear the temporary visibility flag.
|
||||||
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
|
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
|
||||||
m_foundItems.GetItem( data )->SetForceVisible( false );
|
item->SetForceVisible( false );
|
||||||
else
|
else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() )
|
||||||
m_foundItems.GetItem( data )->SetForceVisible( true );
|
item->SetForceVisible( true );
|
||||||
|
|
||||||
if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
|
if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
|
||||||
{
|
{
|
||||||
|
@ -371,61 +454,3 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
||||||
|
|
||||||
SetStatusText( msg );
|
SetStatusText( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnFindReplace( wxFindDialogEvent& aEvent )
|
|
||||||
{
|
|
||||||
SCH_FIND_COLLECTOR_DATA data;
|
|
||||||
|
|
||||||
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
|
|
||||||
SCH_ITEM* item = (SCH_ITEM*) m_foundItems.GetItem( data );
|
|
||||||
|
|
||||||
wxCHECK_RET( item != NULL, wxT( "Invalid replace item in find collector list." ) );
|
|
||||||
|
|
||||||
wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ),
|
|
||||||
GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ),
|
|
||||||
GetChars( m_foundItems.GetText() ) );
|
|
||||||
|
|
||||||
SCH_ITEM* undoItem = data.GetParent();
|
|
||||||
|
|
||||||
if( undoItem == NULL )
|
|
||||||
undoItem = item;
|
|
||||||
|
|
||||||
SetUndoItem( undoItem );
|
|
||||||
|
|
||||||
if( m_foundItems.ReplaceItem() )
|
|
||||||
{
|
|
||||||
OnModify();
|
|
||||||
SaveUndoItemInUndoList( undoItem );
|
|
||||||
RedrawScreen( data.GetPosition(), warpCursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
OnFindSchematicItem( aEvent );
|
|
||||||
|
|
||||||
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_REPLACE_ALL )
|
|
||||||
{
|
|
||||||
while( ( item = (SCH_ITEM*) m_foundItems.GetItem( data ) ) != NULL )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceFindReplace, wxT( "Replacing %s with %s in item %s" ),
|
|
||||||
GetChars( aEvent.GetFindString() ), GetChars( aEvent.GetReplaceString() ),
|
|
||||||
GetChars( m_foundItems.GetText() ) );
|
|
||||||
|
|
||||||
SCH_ITEM* undoItem = data.GetParent();
|
|
||||||
|
|
||||||
// Don't save child items in undo list.
|
|
||||||
if( undoItem == NULL )
|
|
||||||
undoItem = item;
|
|
||||||
|
|
||||||
SetUndoItem( undoItem );
|
|
||||||
|
|
||||||
if( m_foundItems.ReplaceItem() )
|
|
||||||
{
|
|
||||||
OnModify();
|
|
||||||
SaveUndoItemInUndoList( undoItem );
|
|
||||||
RedrawScreen( data.GetPosition(), warpCursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
OnFindSchematicItem( aEvent );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -640,7 +640,7 @@ void LIB_FIELD::SetName( const wxString& aName )
|
||||||
// Besides, m_id is a relic that is untrustworthy now.
|
// Besides, m_id is a relic that is untrustworthy now.
|
||||||
if( m_id >=0 && m_id < MANDATORY_FIELDS )
|
if( m_id >=0 && m_id < MANDATORY_FIELDS )
|
||||||
{
|
{
|
||||||
D(printf( "trying to set a MANDATORY_FIELD's name\n" );)
|
DBG(printf( "trying to set a MANDATORY_FIELD's name\n" );)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,7 +424,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
|
||||||
wxFileName tmpFile = aFullFileName;
|
wxFileName tmpFile = aFullFileName;
|
||||||
tmpFile.SetExt( INTERMEDIATE_NETLIST_EXT );
|
tmpFile.SetExt( INTERMEDIATE_NETLIST_EXT );
|
||||||
|
|
||||||
D(printf("tmpFile:'%s'\n", TO_UTF8( tmpFile.GetFullPath() ) );)
|
DBG(printf("tmpFile:'%s'\n", TO_UTF8( tmpFile.GetFullPath() ) );)
|
||||||
|
|
||||||
ret = helper.WriteGENERICNetList( tmpFile.GetFullPath() );
|
ret = helper.WriteGENERICNetList( tmpFile.GetFullPath() );
|
||||||
if( !ret )
|
if( !ret )
|
||||||
|
@ -442,7 +442,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
|
||||||
tmpFile.GetFullPath(),
|
tmpFile.GetFullPath(),
|
||||||
aFullFileName );
|
aFullFileName );
|
||||||
|
|
||||||
D(printf("commandLine:'%s'\n", TO_UTF8( commandLine ) );)
|
DBG(printf("commandLine:'%s'\n", TO_UTF8( commandLine ) );)
|
||||||
|
|
||||||
ProcessExecute( commandLine, wxEXEC_SYNC );
|
ProcessExecute( commandLine, wxEXEC_SYNC );
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,7 +347,7 @@ bool SCH_FIND_COLLECTOR::PassedEnd() const
|
||||||
if( GetCount() == 0 )
|
if( GetCount() == 0 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( !(flags & FR_SEARCH_WRAP) )
|
if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
|
||||||
{
|
{
|
||||||
if( flags & wxFR_DOWN )
|
if( flags & wxFR_DOWN )
|
||||||
{
|
{
|
||||||
|
@ -454,7 +454,7 @@ EDA_ITEM* SCH_FIND_COLLECTOR::GetItem( SCH_FIND_COLLECTOR_DATA& aData )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SCH_FIND_COLLECTOR::ReplaceItem()
|
bool SCH_FIND_COLLECTOR::ReplaceItem( SCH_SHEET_PATH* aSheetPath )
|
||||||
{
|
{
|
||||||
if( PassedEnd() )
|
if( PassedEnd() )
|
||||||
return false;
|
return false;
|
||||||
|
@ -464,15 +464,10 @@ bool SCH_FIND_COLLECTOR::ReplaceItem()
|
||||||
|
|
||||||
EDA_ITEM* item = m_List[ m_foundIndex ];
|
EDA_ITEM* item = m_List[ m_foundIndex ];
|
||||||
|
|
||||||
bool replaced = item->Replace( m_findReplaceData );
|
bool replaced = item->Replace( m_findReplaceData, aSheetPath );
|
||||||
|
|
||||||
// If the replace was successful, remove the item from the find list to prevent
|
|
||||||
// iterating back over it again.
|
|
||||||
if( replaced )
|
if( replaced )
|
||||||
{
|
m_forceSearch = true;
|
||||||
Remove( m_foundIndex );
|
|
||||||
m_data.erase( m_data.begin() + m_foundIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
return replaced;
|
return replaced;
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,15 +237,6 @@ class SCH_FIND_COLLECTOR : public COLLECTOR
|
||||||
/// performed even if the search criteria hasn't changed.
|
/// performed even if the search criteria hasn't changed.
|
||||||
bool m_forceSearch;
|
bool m_forceSearch;
|
||||||
|
|
||||||
/**
|
|
||||||
* Function PassedEnd
|
|
||||||
* tests if #m_foundIndex is beyond the end of the list give the current
|
|
||||||
* find/replace criterial in #m_findReplaceData.
|
|
||||||
*
|
|
||||||
* @return True if #m_foundIndex has crossed the end of the found item list.
|
|
||||||
*/
|
|
||||||
bool PassedEnd() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function dump
|
* Function dump
|
||||||
* is a helper to dump the items in the find list for debugging purposes.
|
* is a helper to dump the items in the find list for debugging purposes.
|
||||||
|
@ -266,8 +257,24 @@ public:
|
||||||
m_forceSearch = false;
|
m_forceSearch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Empty()
|
||||||
|
{
|
||||||
|
m_foundIndex = 0;
|
||||||
|
COLLECTOR::Empty();
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void SetForceSearch() { m_forceSearch = true; }
|
void SetForceSearch() { m_forceSearch = true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function PassedEnd
|
||||||
|
* tests if #m_foundIndex is beyond the end of the list give the current
|
||||||
|
* find/replace criterial in #m_findReplaceData.
|
||||||
|
*
|
||||||
|
* @return True if #m_foundIndex has crossed the end of the found item list.
|
||||||
|
*/
|
||||||
|
bool PassedEnd() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function UpdateIndex
|
* Function UpdateIndex
|
||||||
* updates the list index according to the current find and replace criteria.
|
* updates the list index according to the current find and replace criteria.
|
||||||
|
@ -326,7 +333,7 @@ public:
|
||||||
*
|
*
|
||||||
* @return True if the text replace occurred otherwise false.
|
* @return True if the text replace occurred otherwise false.
|
||||||
*/
|
*/
|
||||||
bool ReplaceItem();
|
bool ReplaceItem( SCH_SHEET_PATH* aSheetPath = NULL );
|
||||||
|
|
||||||
SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL );
|
SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL );
|
||||||
|
|
||||||
|
@ -340,6 +347,8 @@ public:
|
||||||
* value searches the entire schematic hierarchy.
|
* value searches the entire schematic hierarchy.
|
||||||
*/
|
*/
|
||||||
void Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath = NULL );
|
void Collect( SCH_FIND_REPLACE_DATA& aFindReplaceData, SCH_SHEET_PATH* aSheetPath = NULL );
|
||||||
|
|
||||||
|
void IncrementIndex() { m_foundIndex += 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -431,8 +431,11 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
|
||||||
bool isReplaced;
|
bool isReplaced;
|
||||||
wxString text = GetFullyQualifiedText();
|
wxString text = GetFullyQualifiedText();
|
||||||
|
|
||||||
if( m_id == REFERENCE && aAuxData != NULL )
|
if( m_id == REFERENCE )
|
||||||
{
|
{
|
||||||
|
wxCHECK_MSG( aAuxData != NULL, false,
|
||||||
|
wxT( "Cannot replace reference designator without valid sheet path." ) );
|
||||||
|
|
||||||
wxCHECK_MSG( aSearchData.GetFlags() & FR_REPLACE_REFERENCES, false,
|
wxCHECK_MSG( aSearchData.GetFlags() & FR_REPLACE_REFERENCES, false,
|
||||||
wxT( "Invalid replace component reference field call." ) ) ;
|
wxT( "Invalid replace component reference field call." ) ) ;
|
||||||
|
|
||||||
|
@ -443,8 +446,8 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
|
||||||
|
|
||||||
text = component->GetRef( (SCH_SHEET_PATH*) aAuxData );
|
text = component->GetRef( (SCH_SHEET_PATH*) aAuxData );
|
||||||
|
|
||||||
if( component->GetPartCount() > 1 )
|
// if( component->GetPartCount() > 1 )
|
||||||
text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() );
|
// text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() );
|
||||||
|
|
||||||
isReplaced = EDA_ITEM::Replace( aSearchData, text );
|
isReplaced = EDA_ITEM::Replace( aSearchData, text );
|
||||||
|
|
||||||
|
|
|
@ -438,6 +438,7 @@ SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet )
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
m_List = NULL;
|
m_List = NULL;
|
||||||
|
m_isRootSheet = false;
|
||||||
|
|
||||||
if( aSheet == NULL )
|
if( aSheet == NULL )
|
||||||
aSheet = g_RootSheet;
|
aSheet = g_RootSheet;
|
||||||
|
@ -518,6 +519,9 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::GetSheet( const wxString aPath, bool aHumanReada
|
||||||
|
|
||||||
void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
|
void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
|
||||||
{
|
{
|
||||||
|
if( aSheet == g_RootSheet )
|
||||||
|
m_isRootSheet = true;
|
||||||
|
|
||||||
if( m_List == NULL )
|
if( m_List == NULL )
|
||||||
{
|
{
|
||||||
int count = aSheet->CountSheets();
|
int count = aSheet->CountSheets();
|
||||||
|
@ -702,3 +706,25 @@ bool SCH_SHEET_LIST::SetComponentFootprint( const wxString& aReference,
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCH_SHEET_LIST::IsComplexHierarchy()
|
||||||
|
{
|
||||||
|
wxString fileName;
|
||||||
|
|
||||||
|
for( int i = 0; i < GetCount(); i++ )
|
||||||
|
{
|
||||||
|
fileName = GetSheet( i )->Last()->GetFileName();
|
||||||
|
|
||||||
|
for( int j = 0; j < GetCount(); j++ )
|
||||||
|
{
|
||||||
|
if( i == j )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( fileName == GetSheet( j )->Last()->GetFileName() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -292,6 +292,7 @@ private:
|
||||||
* returning the next item in m_List. Also used for
|
* returning the next item in m_List. Also used for
|
||||||
* internal calculations in BuildSheetList()
|
* internal calculations in BuildSheetList()
|
||||||
*/
|
*/
|
||||||
|
bool m_isRootSheet;
|
||||||
SCH_SHEET_PATH m_currList;
|
SCH_SHEET_PATH m_currList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -442,6 +443,15 @@ public:
|
||||||
bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
|
bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
|
||||||
bool aSetVisible );
|
bool aSetVisible );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function IsComplexHierarchy
|
||||||
|
* searches all of the sheets for duplicate files names which indicates a complex
|
||||||
|
* hierarchy.
|
||||||
|
*
|
||||||
|
* @return true if the #SCH_SHEET_LIST is a complex hierarchy.
|
||||||
|
*/
|
||||||
|
bool IsComplexHierarchy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -351,7 +351,7 @@ SCH_SCREEN* SCH_EDIT_FRAME::GetScreen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString SCH_EDIT_FRAME::GetScreenDesc()
|
wxString SCH_EDIT_FRAME::GetScreenDesc() const
|
||||||
{
|
{
|
||||||
wxString s = m_CurrentSheet->PathHumanReadable();
|
wxString s = m_CurrentSheet->PathHumanReadable();
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ int TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName )
|
||||||
{
|
{
|
||||||
if( m_Fields[i].m_Name == aFieldName.m_Name )
|
if( m_Fields[i].m_Name == aFieldName.m_Name )
|
||||||
{
|
{
|
||||||
D( printf( "inserting template fieldname:'%s' at %d\n",
|
DBG( printf( "inserting template fieldname:'%s' at %d\n",
|
||||||
TO_UTF8( aFieldName.m_Name ), i ); )
|
TO_UTF8( aFieldName.m_Name ), i ); )
|
||||||
|
|
||||||
m_Fields[i] = aFieldName;
|
m_Fields[i] = aFieldName;
|
||||||
|
@ -159,7 +159,7 @@ int TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// D(printf("appending template fieldname:'%s'\n", aFieldName.m_Name.utf8_str() );)
|
// DBG(printf("appending template fieldname:'%s'\n", aFieldName.m_Name.utf8_str() );)
|
||||||
|
|
||||||
// the name is legal and not previously added to the config container, append
|
// the name is legal and not previously added to the config container, append
|
||||||
// it and return its index within the container.
|
// it and return its index within the container.
|
||||||
|
|
|
@ -409,7 +409,7 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
|
||||||
|
|
||||||
case AMP_UNKNOWN:
|
case AMP_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
D( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
|
DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
||||||
if( m_GerbMetric )
|
if( m_GerbMetric )
|
||||||
conv_scale /= 25.4;
|
conv_scale /= 25.4;
|
||||||
|
|
||||||
// D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); )
|
// DBG( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); )
|
||||||
|
|
||||||
switch( command )
|
switch( command )
|
||||||
{
|
{
|
||||||
|
@ -521,7 +521,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
||||||
m_ImageNegative = true;
|
m_ImageNegative = true;
|
||||||
else
|
else
|
||||||
m_ImageNegative = false;
|
m_ImageNegative = false;
|
||||||
D( printf( "%22s: IMAGE_POLARITY m_ImageNegative=%s\n", __func__,
|
DBG( printf( "%22s: IMAGE_POLARITY m_ImageNegative=%s\n", __func__,
|
||||||
m_ImageNegative ? "true" : "false" ); )
|
m_ImageNegative ? "true" : "false" ); )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
||||||
|
|
||||||
else
|
else
|
||||||
GetLayerParams().m_LayerNegative = false;
|
GetLayerParams().m_LayerNegative = false;
|
||||||
D( printf( "%22s: LAYER_POLARITY m_LayerNegative=%s\n", __func__,
|
DBG( printf( "%22s: LAYER_POLARITY m_LayerNegative=%s\n", __func__,
|
||||||
GetLayerParams().m_LayerNegative ? "true" : "false" ); )
|
GetLayerParams().m_LayerNegative ? "true" : "false" ); )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <colors.h>
|
#include <colors.h>
|
||||||
#include <bitmaps.h>
|
#include <bitmaps.h>
|
||||||
#include <richio.h>
|
#include <richio.h>
|
||||||
|
#include <view/view_item.h>
|
||||||
|
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
@ -46,102 +47,8 @@ extern std::ostream& operator <<( std::ostream& out, const wxPoint& pt );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/// Flag to enable find and replace tracing using the WXTRACE environment variable.
|
||||||
* Enum KICAD_T
|
extern const wxString traceFindReplace;
|
||||||
* is the set of class identification values, stored in EDA_ITEM::m_StructType
|
|
||||||
*/
|
|
||||||
enum KICAD_T {
|
|
||||||
NOT_USED = -1, ///< the 3d code uses this value
|
|
||||||
|
|
||||||
EOT = 0, ///< search types array terminator (End Of Types)
|
|
||||||
|
|
||||||
TYPE_NOT_INIT = 0,
|
|
||||||
PCB_T,
|
|
||||||
SCREEN_T, ///< not really an item, used to identify a screen
|
|
||||||
|
|
||||||
// Items in pcb
|
|
||||||
PCB_MODULE_T, ///< class MODULE, a footprint
|
|
||||||
PCB_PAD_T, ///< class D_PAD, a pad in a footprint
|
|
||||||
PCB_LINE_T, ///< class DRAWSEGMENT, a segment not on copper layers
|
|
||||||
PCB_TEXT_T, ///< class TEXTE_PCB, text on a layer
|
|
||||||
PCB_MODULE_TEXT_T, ///< class TEXTE_MODULE, text in a footprint
|
|
||||||
PCB_MODULE_EDGE_T, ///< class EDGE_MODULE, a footprint edge
|
|
||||||
PCB_TRACE_T, ///< class TRACKE, a track segment (segment on a copper layer)
|
|
||||||
PCB_VIA_T, ///< class SEGVIA, a via (like a track segment on a copper layer)
|
|
||||||
PCB_ZONE_T, ///< class SEGZONE, a segment used to fill a zone area (segment on a
|
|
||||||
///< copper layer)
|
|
||||||
PCB_MARKER_T, ///< class MARKER_PCB, a marker used to show something
|
|
||||||
PCB_DIMENSION_T, ///< class DIMENSION, a dimension (graphic item)
|
|
||||||
PCB_TARGET_T, ///< class PCB_TARGET, a target (graphic item)
|
|
||||||
PCB_ZONE_AREA_T, ///< class ZONE_CONTAINER, a zone area
|
|
||||||
PCB_ITEM_LIST_T, ///< class BOARD_ITEM_LIST, a list of board items
|
|
||||||
|
|
||||||
// Schematic draw Items. The order of these items effects the sort order.
|
|
||||||
// It is currently ordered to mimic the old Eeschema locate behavior where
|
|
||||||
// the smallest item is the selected item.
|
|
||||||
SCH_MARKER_T,
|
|
||||||
SCH_JUNCTION_T,
|
|
||||||
SCH_NO_CONNECT_T,
|
|
||||||
SCH_BUS_WIRE_ENTRY_T,
|
|
||||||
SCH_BUS_BUS_ENTRY_T,
|
|
||||||
SCH_LINE_T,
|
|
||||||
SCH_BITMAP_T,
|
|
||||||
SCH_TEXT_T,
|
|
||||||
SCH_LABEL_T,
|
|
||||||
SCH_GLOBAL_LABEL_T,
|
|
||||||
SCH_HIERARCHICAL_LABEL_T,
|
|
||||||
SCH_FIELD_T,
|
|
||||||
SCH_COMPONENT_T,
|
|
||||||
SCH_SHEET_PIN_T,
|
|
||||||
SCH_SHEET_T,
|
|
||||||
|
|
||||||
// Be prudent with these 3 types:
|
|
||||||
// they should be used only to locate a specific field type
|
|
||||||
// among SCH_FIELD_T items types
|
|
||||||
SCH_FIELD_LOCATE_REFERENCE_T,
|
|
||||||
SCH_FIELD_LOCATE_VALUE_T,
|
|
||||||
SCH_FIELD_LOCATE_FOOTPRINT_T,
|
|
||||||
|
|
||||||
// General
|
|
||||||
SCH_SCREEN_T,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Draw items in library component.
|
|
||||||
*
|
|
||||||
* The order of these items effects the sort order for items inside the
|
|
||||||
* "DRAW/ENDDRAW" section of the component definition in a library file.
|
|
||||||
* If you add a new draw item, type, please make sure you add it so the
|
|
||||||
* sort order is logical.
|
|
||||||
*/
|
|
||||||
LIB_COMPONENT_T,
|
|
||||||
LIB_ALIAS_T,
|
|
||||||
LIB_ARC_T,
|
|
||||||
LIB_CIRCLE_T,
|
|
||||||
LIB_TEXT_T,
|
|
||||||
LIB_RECTANGLE_T,
|
|
||||||
LIB_POLYLINE_T,
|
|
||||||
LIB_BEZIER_T,
|
|
||||||
LIB_PIN_T,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fields are not saved inside the "DRAW/ENDDRAW". Add new draw item
|
|
||||||
* types before this line.
|
|
||||||
*/
|
|
||||||
LIB_FIELD_T,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For GerbView: items type:
|
|
||||||
*/
|
|
||||||
TYPE_GERBER_DRAW_ITEM,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* for Pl_Editor, in undo/redo commands
|
|
||||||
*/
|
|
||||||
TYPE_PL_EDITOR_LAYOUT,
|
|
||||||
|
|
||||||
// End value
|
|
||||||
MAX_STRUCT_TYPE_ID
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -400,6 +307,9 @@ public:
|
||||||
#define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad
|
#define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad
|
||||||
#define BUSY (1 << 24) ///< Pcbnew: flag indicating that the structure has
|
#define BUSY (1 << 24) ///< Pcbnew: flag indicating that the structure has
|
||||||
///< already been edited, in some functions
|
///< already been edited, in some functions
|
||||||
|
#define HIGHLIGHTED (1 << 25) ///< item is drawn in normal colors, when the rest is darkened
|
||||||
|
#define BRIGHTENED (1 << 26) ///< item is drawn with a bright contour
|
||||||
|
|
||||||
#define EDA_ITEM_ALL_FLAGS -1
|
#define EDA_ITEM_ALL_FLAGS -1
|
||||||
|
|
||||||
typedef unsigned STATUS_FLAGS;
|
typedef unsigned STATUS_FLAGS;
|
||||||
|
@ -409,7 +319,7 @@ typedef unsigned STATUS_FLAGS;
|
||||||
* is a base class for most all the KiCad significant classes, used in
|
* is a base class for most all the KiCad significant classes, used in
|
||||||
* schematics and boards.
|
* schematics and boards.
|
||||||
*/
|
*/
|
||||||
class EDA_ITEM
|
class EDA_ITEM : public KIGFX::VIEW_ITEM
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -450,12 +360,7 @@ public:
|
||||||
EDA_ITEM( const EDA_ITEM& base );
|
EDA_ITEM( const EDA_ITEM& base );
|
||||||
virtual ~EDA_ITEM() { };
|
virtual ~EDA_ITEM() { };
|
||||||
|
|
||||||
/**
|
/// @copydoc VIEW_ITEM::Type()
|
||||||
* Function Type
|
|
||||||
* returns the type of object. This attribute should never be changed
|
|
||||||
* after a constructor sets it, so there is no public "setter" method.
|
|
||||||
* @return KICAD_T - the type of object.
|
|
||||||
*/
|
|
||||||
KICAD_T Type() const { return m_StructType; }
|
KICAD_T Type() const { return m_StructType; }
|
||||||
|
|
||||||
void SetTimeStamp( time_t aNewTimeStamp ) { m_TimeStamp = aNewTimeStamp; }
|
void SetTimeStamp( time_t aNewTimeStamp ) { m_TimeStamp = aNewTimeStamp; }
|
||||||
|
@ -479,6 +384,16 @@ public:
|
||||||
inline bool IsDragging() const { return m_Flags & IS_DRAGGED; }
|
inline bool IsDragging() const { return m_Flags & IS_DRAGGED; }
|
||||||
inline bool IsSelected() const { return m_Flags & SELECTED; }
|
inline bool IsSelected() const { return m_Flags & SELECTED; }
|
||||||
inline bool IsResized() const { return m_Flags & IS_RESIZED; }
|
inline bool IsResized() const { return m_Flags & IS_RESIZED; }
|
||||||
|
inline bool IsHighlighted() const { return m_Flags & HIGHLIGHTED; }
|
||||||
|
inline bool IsBrightened() const { return m_Flags & BRIGHTENED; }
|
||||||
|
|
||||||
|
inline void SetSelected() { SetFlags( SELECTED ); ViewUpdate( COLOR ); }
|
||||||
|
inline void SetHighlighted() { SetFlags( HIGHLIGHTED ); ViewUpdate( COLOR ); }
|
||||||
|
inline void SetBrightened() { SetFlags( BRIGHTENED ); }
|
||||||
|
|
||||||
|
inline void ClearSelected() { ClearFlags( SELECTED ); ViewUpdate( COLOR ); }
|
||||||
|
inline void ClearHighlighted() { ClearFlags( HIGHLIGHTED ); ViewUpdate( COLOR ); }
|
||||||
|
inline void ClearBrightened() { ClearFlags( BRIGHTENED ); }
|
||||||
|
|
||||||
void SetModified();
|
void SetModified();
|
||||||
|
|
||||||
|
@ -748,6 +663,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual EDA_ITEM& operator=( const EDA_ITEM& aItem );
|
virtual EDA_ITEM& operator=( const EDA_ITEM& aItem );
|
||||||
|
|
||||||
|
/// @copydoc VIEW_ITEM::ViewBBox()
|
||||||
|
virtual const BOX2I ViewBBox() const;
|
||||||
|
|
||||||
|
/// @copydoc VIEW_ITEM::ViewGetLayers()
|
||||||
|
virtual void ViewGetLayers( int aLayers[], int& aCount ) const;
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,6 +90,10 @@ public:
|
||||||
|
|
||||||
// Do not create a copy constructor. The one generated by the compiler is adequate.
|
// Do not create a copy constructor. The one generated by the compiler is adequate.
|
||||||
|
|
||||||
|
virtual const wxPoint& GetPosition() const = 0;
|
||||||
|
|
||||||
|
virtual void SetPosition( const wxPoint& aPos ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value of wxPoint(0,0) which can be passed to the Draw() functions.
|
* A value of wxPoint(0,0) which can be passed to the Draw() functions.
|
||||||
*/
|
*/
|
||||||
|
@ -269,6 +273,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 */
|
||||||
|
|
|
@ -317,6 +317,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground = true );
|
void RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground = true );
|
||||||
|
|
||||||
|
/// @copydoc wxWindow::Refresh()
|
||||||
|
virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetScreenCenterLogicalPosition
|
* Function GetScreenCenterLogicalPosition
|
||||||
* @return The current screen center position in logical (drawing) units.
|
* @return The current screen center position in logical (drawing) units.
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* 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 class_drawpanel_gal.h:
|
||||||
|
* @brief EDA_DRAW_PANEL_GAL class definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PANELGAL_WXSTRUCT_H
|
||||||
|
#define PANELGAL_WXSTRUCT_H
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/window.h>
|
||||||
|
|
||||||
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
|
class BOARD;
|
||||||
|
class TOOL_DISPATCHER;
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
class GAL;
|
||||||
|
class VIEW;
|
||||||
|
class WX_VIEW_CONTROLS;
|
||||||
|
class VIEW_CONTROLS;
|
||||||
|
class PAINTER;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class EDA_DRAW_PANEL_GAL : public wxWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum GalType {
|
||||||
|
GAL_TYPE_NONE, ///< Not used
|
||||||
|
GAL_TYPE_OPENGL, ///< OpenGL implementation
|
||||||
|
GAL_TYPE_CAIRO, ///< Cairo implementation
|
||||||
|
};
|
||||||
|
|
||||||
|
EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, const wxPoint& aPosition,
|
||||||
|
const wxSize& aSize, GalType aGalType = GAL_TYPE_OPENGL );
|
||||||
|
~EDA_DRAW_PANEL_GAL();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SwitchBackend
|
||||||
|
* Switches method of rendering graphics.
|
||||||
|
* @param aGalType is a type of rendering engine that you want to use.
|
||||||
|
*/
|
||||||
|
void SwitchBackend( GalType aGalType );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetGAL()
|
||||||
|
* Returns a pointer to the GAL instance used in the panel.
|
||||||
|
* @return The instance of GAL.
|
||||||
|
*/
|
||||||
|
KIGFX::GAL* GetGAL() const
|
||||||
|
{
|
||||||
|
return m_gal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetView()
|
||||||
|
* Returns a pointer to the VIEW instance used in the panel.
|
||||||
|
* @return The instance of VIEW.
|
||||||
|
*/
|
||||||
|
KIGFX::VIEW* GetView() const
|
||||||
|
{
|
||||||
|
return m_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetViewControls()
|
||||||
|
* Returns a pointer to the VIEW_CONTROLS instance used in the panel.
|
||||||
|
* @return The instance of VIEW_CONTROLS.
|
||||||
|
*/
|
||||||
|
KIGFX::VIEW_CONTROLS* GetViewControls() const
|
||||||
|
{
|
||||||
|
return (KIGFX::VIEW_CONTROLS*)( m_viewControls );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc wxWindow::Refresh()
|
||||||
|
virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetEventDispatcher()
|
||||||
|
* Sets a dispatcher that processes events and forwards them to tools.
|
||||||
|
* @param aEventDispatcher is the object that will be used for dispatching events.
|
||||||
|
*/
|
||||||
|
void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher )
|
||||||
|
{
|
||||||
|
m_eventDispatcher = aEventDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onPaint( wxPaintEvent& WXUNUSED( aEvent ) );
|
||||||
|
void onSize( wxSizeEvent& aEvent );
|
||||||
|
void onEvent( wxEvent& aEvent );
|
||||||
|
void onEnter( wxEvent& aEvent );
|
||||||
|
void onRefreshTimer ( wxTimerEvent& aEvent );
|
||||||
|
void skipEvent( wxEvent& aEvent );
|
||||||
|
|
||||||
|
static const int MinRefreshPeriod = 17; ///< 60 FPS.
|
||||||
|
|
||||||
|
wxLongLong m_lastRefresh; ///< Last time the panel was refreshed
|
||||||
|
bool m_pendingRefresh;
|
||||||
|
wxTimer m_refreshTimer;
|
||||||
|
|
||||||
|
KIGFX::GAL* m_gal; ///< Interface for drawing objects on a 2D-surface
|
||||||
|
KIGFX::VIEW* m_view; ///< Stores view settings (scale, center, etc.)
|
||||||
|
///< and items to be drawn
|
||||||
|
KIGFX::PAINTER* m_painter; ///< Contains information about how to draw items
|
||||||
|
///< using GAL
|
||||||
|
KIGFX::WX_VIEW_CONTROLS* m_viewControls; ///< Control for VIEW (moving, zooming, etc.)
|
||||||
|
GalType m_currentGal; ///< Currently used GAL
|
||||||
|
TOOL_DISPATCHER* m_eventDispatcher; ///< Processes and forwards events to tools
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -6,7 +6,7 @@
|
||||||
#ifndef CLASS_WORKSHEET_DATA_ITEM_H
|
#ifndef CLASS_WORKSHEET_DATA_ITEM_H
|
||||||
#define CLASS_WORKSHEET_DATA_ITEM_H
|
#define CLASS_WORKSHEET_DATA_ITEM_H
|
||||||
|
|
||||||
#include <vector2d.h>
|
#include <math/vector2d.h>
|
||||||
#include <eda_text.h>
|
#include <eda_text.h>
|
||||||
#include <class_bitmap_base.h>
|
#include <class_bitmap_base.h>
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,14 @@ EDA_COLOR_T ColorByName( const wxChar *aName );
|
||||||
/// Find the nearest color match
|
/// Find the nearest color match
|
||||||
EDA_COLOR_T ColorFindNearest( const wxColour &aColor );
|
EDA_COLOR_T ColorFindNearest( const wxColour &aColor );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the nearest color match
|
||||||
|
* @param aR is the red component of the color to be matched (in range 0-255)
|
||||||
|
* @param aG is the green component of the color to be matched (in range 0-255)
|
||||||
|
* @param aG is the blue component of the color to be matched (in range 0-255)
|
||||||
|
*/
|
||||||
|
EDA_COLOR_T ColorFindNearest( int aR, int aG, int aB );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a color is light i.e. if black would be more readable than
|
* Check if a color is light i.e. if black would be more readable than
|
||||||
* white on it
|
* white on it
|
||||||
|
|
|
@ -236,6 +236,8 @@ public:
|
||||||
* for single line text, aLine is unused
|
* for single line text, aLine is unused
|
||||||
* If aLine == -1, the full area (considering all lines) is returned
|
* If aLine == -1, the full area (considering all lines) is returned
|
||||||
* @param aThickness Overrides the current thickness when greater than 0.
|
* @param aThickness Overrides the current thickness when greater than 0.
|
||||||
|
* this is needed when the current m_Thickness is 0 and a default line thickness
|
||||||
|
* is used
|
||||||
* @param aInvertY Invert the Y axis when calculating bounding box.
|
* @param aInvertY Invert the Y axis when calculating bounding box.
|
||||||
*/
|
*/
|
||||||
EDA_RECT GetTextBox( int aLine = -1, int aThickness = -1, bool aInvertY = false ) const;
|
EDA_RECT GetTextBox( int aLine = -1, int aThickness = -1, bool aInvertY = false ) const;
|
||||||
|
@ -244,11 +246,11 @@ public:
|
||||||
* Function GetInterline
|
* Function GetInterline
|
||||||
* return the distance between 2 text lines
|
* return the distance between 2 text lines
|
||||||
* has meaning only for multiline texts
|
* has meaning only for multiline texts
|
||||||
|
* @param aTextThickness Overrides the current thickness when greater than 0.
|
||||||
|
* this is needed when the current m_Thickness is 0 and a default line thickness
|
||||||
|
* is used
|
||||||
*/
|
*/
|
||||||
int GetInterline() const
|
int GetInterline( int aTextThickness = -1 ) const;
|
||||||
{
|
|
||||||
return (( m_Size.y * 14 ) / 10) + m_Thickness;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetTextStyleName
|
* Function GetTextStyleName
|
||||||
|
@ -286,15 +288,13 @@ private:
|
||||||
* @param aColor = text color
|
* @param aColor = text color
|
||||||
* @param aDrawMode = GR_OR, GR_XOR.., -1 to use the current mode.
|
* @param aDrawMode = GR_OR, GR_XOR.., -1 to use the current mode.
|
||||||
* @param aFillMode = LINE, FILLED or SKETCH
|
* @param aFillMode = LINE, FILLED or SKETCH
|
||||||
* @param aAnchor_color = anchor color ( UNSPECIFIED_COLOR = do not draw anchor ).
|
|
||||||
* @param aText = the single line of text to draw.
|
* @param aText = the single line of text to draw.
|
||||||
* @param aPos = the position of this line ).
|
* @param aPos = the position of this line ).
|
||||||
*/
|
*/
|
||||||
void drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
void drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
||||||
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
||||||
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
||||||
EDA_COLOR_T aAnchor_color, wxString& aText,
|
wxString& aText, wxPoint aPos );
|
||||||
wxPoint aPos );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
#define WIN_STRING_DIR_SEP wxT( "\\" )
|
#define WIN_STRING_DIR_SEP wxT( "\\" )
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define D(x) x
|
#define DBG(x) x
|
||||||
#else
|
#else
|
||||||
#define D(x) // nothing
|
#define DBG(x) // nothing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file cairo_compositor.h
|
||||||
|
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
|
||||||
|
* later compositing into a single image (Cairo flavour).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAIRO_COMPOSITOR_H_
|
||||||
|
#define CAIRO_COMPOSITOR_H_
|
||||||
|
|
||||||
|
#include <gal/compositor.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <boost/smart_ptr/shared_array.hpp>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
class CAIRO_COMPOSITOR : public COMPOSITOR
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CAIRO_COMPOSITOR( cairo_t** aMainContext );
|
||||||
|
virtual ~CAIRO_COMPOSITOR();
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::Initialize()
|
||||||
|
virtual void Initialize();
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::Resize()
|
||||||
|
virtual void Resize( unsigned int aWidth, unsigned int aHeight );
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::CreateBuffer()
|
||||||
|
virtual unsigned int CreateBuffer();
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::GetBuffer()
|
||||||
|
inline virtual unsigned int GetBuffer() const
|
||||||
|
{
|
||||||
|
return m_current + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::SetBuffer()
|
||||||
|
virtual void SetBuffer( unsigned int aBufferHandle );
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::ClearBuffer()
|
||||||
|
virtual void ClearBuffer();
|
||||||
|
|
||||||
|
/// @copydoc COMPOSITOR::DrawBuffer()
|
||||||
|
virtual void DrawBuffer( unsigned int aBufferHandle );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetMainContext()
|
||||||
|
* Sets a context to be treated as the main context (ie. as a target of buffers rendering and
|
||||||
|
* as a source of settings for newly created buffers).
|
||||||
|
*
|
||||||
|
* @param aMainContext is the context that should be treated as the main one.
|
||||||
|
*/
|
||||||
|
inline virtual void SetMainContext( cairo_t* aMainContext )
|
||||||
|
{
|
||||||
|
m_mainContext = aMainContext;
|
||||||
|
|
||||||
|
// Use the context's transformation matrix
|
||||||
|
cairo_get_matrix( m_mainContext, &m_matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef boost::shared_array<unsigned int> BitmapPtr;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cairo_t* context; ///< Main texture handle
|
||||||
|
cairo_surface_t* surface; ///< Point to which an image from texture is attached
|
||||||
|
BitmapPtr bitmap; ///< Pixel storage
|
||||||
|
} CAIRO_BUFFER;
|
||||||
|
|
||||||
|
unsigned int m_current; ///< Currently used buffer handle
|
||||||
|
typedef std::deque<CAIRO_BUFFER> CAIRO_BUFFERS;
|
||||||
|
|
||||||
|
/// Pointer to the current context, so it can be changed
|
||||||
|
cairo_t** m_currentContext;
|
||||||
|
|
||||||
|
/// Rendering target used for compositing (the main display)
|
||||||
|
cairo_t* m_mainContext;
|
||||||
|
|
||||||
|
/// Transformation matrix
|
||||||
|
cairo_matrix_t m_matrix;
|
||||||
|
|
||||||
|
/// Stores information about initialized buffers
|
||||||
|
CAIRO_BUFFERS m_buffers;
|
||||||
|
|
||||||
|
unsigned int m_stride; ///< Stride to use given the desired format and width
|
||||||
|
unsigned int m_bufferSize; ///< Amount of memory needed to store a buffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function clean()
|
||||||
|
* performs freeing of resources.
|
||||||
|
*/
|
||||||
|
void clean();
|
||||||
|
|
||||||
|
/// Returns number of currently used buffers
|
||||||
|
unsigned int usedBuffers()
|
||||||
|
{
|
||||||
|
return m_buffers.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* COMPOSITOR_H_ */
|
|
@ -0,0 +1,392 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* CairoGal - Graphics Abstraction Layer for Cairo
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAIROGAL_H_
|
||||||
|
#define CAIROGAL_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
|
#include <wx/dcbuffer.h>
|
||||||
|
|
||||||
|
#if defined(__WXMSW__)
|
||||||
|
#define SCREEN_DEPTH 24
|
||||||
|
#else
|
||||||
|
#if wxCHECK_VERSION( 2, 9, 0 )
|
||||||
|
#define SCREEN_DEPTH wxBITMAP_SCREEN_DEPTH
|
||||||
|
#else
|
||||||
|
#define SCREEN_DEPTH 32
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
|
||||||
|
*
|
||||||
|
* Quote from Wikipedia:
|
||||||
|
* " Cairo is a software library used to provide a vector graphics-based, device-independent
|
||||||
|
* API for software developers. It is designed to provide primitives for 2-dimensional
|
||||||
|
* drawing across a number of different backends. "
|
||||||
|
* <br>
|
||||||
|
* Cairo offers also backends for Postscript and PDF surfaces. So it can be used for printing
|
||||||
|
* of KiCad graphics surfaces as well.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
class CAIRO_COMPOSITOR;
|
||||||
|
|
||||||
|
class CAIRO_GAL : public GAL, public wxWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor CAIRO_GAL
|
||||||
|
*
|
||||||
|
* @param aParent is the wxWidgets immediate wxWindow parent of this object.
|
||||||
|
*
|
||||||
|
* @param aMouseListener is the wxEvtHandler that should receive the mouse events,
|
||||||
|
* this can be can be any wxWindow, but is often a wxFrame container.
|
||||||
|
*
|
||||||
|
* @param aPaintListener is the wxEvtHandler that should receive the paint
|
||||||
|
* event. This can be any wxWindow, but is often a derived instance
|
||||||
|
* of this class or a containing wxFrame. The "paint event" here is
|
||||||
|
* a wxCommandEvent holding EVT_GAL_REDRAW, as sent by PostPaint().
|
||||||
|
*
|
||||||
|
* @param aName is the name of this window for use by wxWindow::FindWindowByName()
|
||||||
|
*/
|
||||||
|
CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener = NULL,
|
||||||
|
wxEvtHandler* aPaintListener = NULL, const wxString& aName = wxT( "CairoCanvas" ) );
|
||||||
|
|
||||||
|
virtual ~CAIRO_GAL();
|
||||||
|
|
||||||
|
// ---------------
|
||||||
|
// Drawing methods
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
/// @copydoc GAL::BeginDrawing()
|
||||||
|
virtual void BeginDrawing();
|
||||||
|
|
||||||
|
/// @copydoc GAL::EndDrawing()
|
||||||
|
virtual void EndDrawing();
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawLine()
|
||||||
|
virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawSegment()
|
||||||
|
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawCircle()
|
||||||
|
virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawArc()
|
||||||
|
virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
|
||||||
|
double aStartAngle, double aEndAngle );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawRectangle()
|
||||||
|
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawPolyline()
|
||||||
|
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawPolygon()
|
||||||
|
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawCurve()
|
||||||
|
virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||||
|
const VECTOR2D& controlPointB, const VECTOR2D& endPoint );
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Screen methods
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
/// @brief Resizes the canvas.
|
||||||
|
virtual void ResizeScreen( int aWidth, int aHeight );
|
||||||
|
|
||||||
|
/// @brief Shows/hides the GAL canvas
|
||||||
|
virtual bool Show( bool aShow );
|
||||||
|
|
||||||
|
/// @copydoc GAL::Flush()
|
||||||
|
virtual void Flush();
|
||||||
|
|
||||||
|
/// @copydoc GAL::ClearScreen()
|
||||||
|
virtual void ClearScreen();
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
// Attribute setting
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetIsFill()
|
||||||
|
virtual void SetIsFill( bool aIsFillEnabled );
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetIsStroke()
|
||||||
|
virtual void SetIsStroke( bool aIsStrokeEnabled );
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetStrokeColor()
|
||||||
|
virtual void SetStrokeColor( const COLOR4D& aColor );
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetFillColor()
|
||||||
|
virtual void SetFillColor( const COLOR4D& aColor );
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetLineWidth()
|
||||||
|
virtual void SetLineWidth( double aLineWidth );
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetLayerDepth()
|
||||||
|
virtual void SetLayerDepth( double aLayerDepth );
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Transformation
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
/// @copydoc GAL::Transform()
|
||||||
|
virtual void Transform( MATRIX3x3D aTransformation );
|
||||||
|
|
||||||
|
/// @copydoc GAL::Rotate()
|
||||||
|
virtual void Rotate( double aAngle );
|
||||||
|
|
||||||
|
/// @copydoc GAL::Translate()
|
||||||
|
virtual void Translate( const VECTOR2D& aTranslation );
|
||||||
|
|
||||||
|
/// @copydoc GAL::Scale()
|
||||||
|
virtual void Scale( const VECTOR2D& aScale );
|
||||||
|
|
||||||
|
/// @copydoc GAL::Save()
|
||||||
|
virtual void Save();
|
||||||
|
|
||||||
|
/// @copydoc GAL::Restore()
|
||||||
|
virtual void Restore();
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// Group methods
|
||||||
|
// ---------------------------------------------
|
||||||
|
|
||||||
|
/// @copydoc GAL::BeginGroup()
|
||||||
|
virtual int BeginGroup();
|
||||||
|
|
||||||
|
/// @copydoc GAL::EndGroup()
|
||||||
|
virtual void EndGroup();
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawGroup()
|
||||||
|
virtual void DrawGroup( int aGroupNumber );
|
||||||
|
|
||||||
|
/// @copydoc GAL::ChangeGroupColor()
|
||||||
|
virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor );
|
||||||
|
|
||||||
|
/// @copydoc GAL::ChangeGroupDepth()
|
||||||
|
virtual void ChangeGroupDepth( int aGroupNumber, int aDepth );
|
||||||
|
|
||||||
|
/// @copydoc GAL::DeleteGroup()
|
||||||
|
virtual void DeleteGroup( int aGroupNumber );
|
||||||
|
|
||||||
|
/// @copydoc GAL::ClearCache()
|
||||||
|
virtual void ClearCache();
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Handling the world <-> screen transformation
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
/// @copydoc GAL::SaveScreen()
|
||||||
|
virtual void SaveScreen();
|
||||||
|
|
||||||
|
/// @copydoc GAL::RestoreScreen()
|
||||||
|
virtual void RestoreScreen();
|
||||||
|
|
||||||
|
/// @copydoc GAL::SetTarget()
|
||||||
|
virtual void SetTarget( RENDER_TARGET aTarget );
|
||||||
|
|
||||||
|
/// @copydoc GAL::GetTarget()
|
||||||
|
virtual RENDER_TARGET GetTarget() const;
|
||||||
|
|
||||||
|
/// @copydoc GAL::ClearTarget()
|
||||||
|
virtual void ClearTarget( RENDER_TARGET aTarget );
|
||||||
|
|
||||||
|
// -------
|
||||||
|
// Cursor
|
||||||
|
// -------
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawCursor()
|
||||||
|
virtual void DrawCursor( const VECTOR2D& aCursorPosition );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function PostPaint
|
||||||
|
* posts an event to m_paint_listener. A post is used so that the actual drawing
|
||||||
|
* function can use a device context type that is not specific to the wxEVT_PAINT event.
|
||||||
|
*/
|
||||||
|
void PostPaint()
|
||||||
|
{
|
||||||
|
if( paintListener )
|
||||||
|
{
|
||||||
|
wxPaintEvent redrawEvent;
|
||||||
|
wxPostEvent( paintListener, redrawEvent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMouseListener( wxEvtHandler* aMouseListener )
|
||||||
|
{
|
||||||
|
mouseListener = aMouseListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPaintListener( wxEvtHandler* aPaintListener )
|
||||||
|
{
|
||||||
|
paintListener = aPaintListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Super class definition
|
||||||
|
typedef GAL super;
|
||||||
|
|
||||||
|
// Compositing variables
|
||||||
|
boost::shared_ptr<CAIRO_COMPOSITOR> compositor; ///< Object for layers compositing
|
||||||
|
unsigned int mainBuffer; ///< Handle to the main buffer
|
||||||
|
unsigned int overlayBuffer; ///< Handle to the overlay buffer
|
||||||
|
RENDER_TARGET currentTarget; ///< Current rendering target
|
||||||
|
bool validCompositor; ///< Compositor initialization flag
|
||||||
|
|
||||||
|
// Variables related to wxWidgets
|
||||||
|
wxWindow* parentWindow; ///< Parent window
|
||||||
|
wxEvtHandler* mouseListener; ///< Mouse listener
|
||||||
|
wxEvtHandler* paintListener; ///< Paint listener
|
||||||
|
unsigned int bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers
|
||||||
|
unsigned char* wxOutput; ///< wxImage comaptible buffer
|
||||||
|
|
||||||
|
// Cursor variables
|
||||||
|
std::deque<wxColour> savedCursorPixels; ///< Saved pixels of the cursor
|
||||||
|
bool isDeleteSavedPixels; ///< True, if the saved pixels can be discarded
|
||||||
|
wxPoint savedCursorPosition; ///< The last cursor position
|
||||||
|
wxBitmap* cursorPixels; ///< Cursor pixels
|
||||||
|
wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels
|
||||||
|
int cursorSize; ///< Cursor size
|
||||||
|
VECTOR2D cursorPosition; ///< Current cursor position
|
||||||
|
|
||||||
|
/// Maximum number of arguments for one command
|
||||||
|
static const int MAX_CAIRO_ARGUMENTS = 6;
|
||||||
|
|
||||||
|
/// Definitions for the command recorder
|
||||||
|
enum GRAPHICS_COMMAND
|
||||||
|
{
|
||||||
|
CMD_SET_FILL, ///< Enable/disable filling
|
||||||
|
CMD_SET_STROKE, ///< Enable/disable stroking
|
||||||
|
CMD_SET_FILLCOLOR, ///< Set the fill color
|
||||||
|
CMD_SET_STROKECOLOR, ///< Set the stroke color
|
||||||
|
CMD_SET_LINE_WIDTH, ///< Set the line width
|
||||||
|
CMD_STROKE_PATH, ///< Set the stroke path
|
||||||
|
CMD_FILL_PATH, ///< Set the fill path
|
||||||
|
CMD_TRANSFORM, ///< Transform the actual context
|
||||||
|
CMD_ROTATE, ///< Rotate the context
|
||||||
|
CMD_TRANSLATE, ///< Translate the context
|
||||||
|
CMD_SCALE, ///< Scale the context
|
||||||
|
CMD_SAVE, ///< Save the transformation matrix
|
||||||
|
CMD_RESTORE, ///< Restore the transformation matrix
|
||||||
|
CMD_CALL_GROUP ///< Call a group
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Type definition for an graphics group element
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GRAPHICS_COMMAND command; ///< Command to execute
|
||||||
|
double arguments[MAX_CAIRO_ARGUMENTS]; ///< Arguments for Cairo commands
|
||||||
|
bool boolArgument; ///< A bool argument
|
||||||
|
int intArgument; ///< An int argument
|
||||||
|
cairo_path_t* cairoPath; ///< Pointer to a Cairo path
|
||||||
|
} GROUP_ELEMENT;
|
||||||
|
|
||||||
|
// Variables for the grouping function
|
||||||
|
bool isGrouping; ///< Is grouping enabled ?
|
||||||
|
bool isElementAdded; ///< Was an graphic element added ?
|
||||||
|
typedef std::deque<GROUP_ELEMENT> GROUP; ///< A graphic group type definition
|
||||||
|
std::map<int, GROUP> groups; ///< List of graphic groups
|
||||||
|
unsigned int groupCounter; ///< Counter used for generating keys for groups
|
||||||
|
GROUP* currentGroup; ///< Currently used group
|
||||||
|
|
||||||
|
// Variables related to Cairo <-> wxWidgets
|
||||||
|
cairo_matrix_t cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix
|
||||||
|
cairo_t* currentContext; ///< Currently used Cairo context for drawing
|
||||||
|
cairo_t* context; ///< Cairo image
|
||||||
|
cairo_surface_t* surface; ///< Cairo surface
|
||||||
|
unsigned int* bitmapBuffer; ///< Storage of the cairo image
|
||||||
|
unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image
|
||||||
|
int stride; ///< Stride value for Cairo
|
||||||
|
bool isInitialized; ///< Are Cairo image & surface ready to use
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
void storePath(); ///< Store the actual path
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
/**
|
||||||
|
* @brief Paint event handler.
|
||||||
|
*
|
||||||
|
* @param aEvent is the paint event.
|
||||||
|
*/
|
||||||
|
void onPaint( wxPaintEvent& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mouse event handler, forwards the event to the child.
|
||||||
|
*
|
||||||
|
* @param aEvent is the mouse event to be forwarded.
|
||||||
|
*/
|
||||||
|
void skipMouseEvent( wxMouseEvent& aEvent );
|
||||||
|
|
||||||
|
/// @copydoc GAL::initCursor()
|
||||||
|
virtual void initCursor( int aCursorSize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Blits cursor into the current screen.
|
||||||
|
*/
|
||||||
|
virtual void blitCursor( wxBufferedDC& clientDC );
|
||||||
|
|
||||||
|
/// Prepare Cairo surfaces for drawing
|
||||||
|
void initSurface();
|
||||||
|
|
||||||
|
/// Destroy Cairo surfaces when are not needed anymore
|
||||||
|
void deinitSurface();
|
||||||
|
|
||||||
|
/// Allocate the bitmaps for drawing
|
||||||
|
void allocateBitmaps();
|
||||||
|
|
||||||
|
/// Allocate the bitmaps for drawing
|
||||||
|
void deleteBitmaps();
|
||||||
|
|
||||||
|
/// Prepare the compositor
|
||||||
|
void setCompositor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a valid key that can be used as a new group number.
|
||||||
|
*
|
||||||
|
* @return An unique group number that is not used by any other group.
|
||||||
|
*/
|
||||||
|
unsigned int getNewGroupNumber();
|
||||||
|
|
||||||
|
/// Format used to store pixels
|
||||||
|
static const cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif // CAIROGAL_H_
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Color 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COLOR4D_H_
|
||||||
|
#define COLOR4D_H_
|
||||||
|
|
||||||
|
#include <colors.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Class COLOR4D
|
||||||
|
* is the color representation with 4 components: red, green, blue, alpha.
|
||||||
|
*/
|
||||||
|
class COLOR4D
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor (creates the Color 0,0,0,0)
|
||||||
|
COLOR4D() :
|
||||||
|
r( 0 ), g( 0 ), b( 0 ), a( 1 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param aRed is the red component [0.0 .. 1.0].
|
||||||
|
* @param aGreen is the green component [0.0 .. 1.0].
|
||||||
|
* @param aBlue is the blue component [0.0 .. 1.0].
|
||||||
|
* @param aAlpha is the alpha value [0.0 .. 1.0].
|
||||||
|
*/
|
||||||
|
COLOR4D( double aRed, double aGreen, double aBlue, double aAlpha ) :
|
||||||
|
r( aRed ), g( aGreen ), b( aBlue ), a( aAlpha )
|
||||||
|
{
|
||||||
|
assert( r >= 0.0 && r <= 1.0 );
|
||||||
|
assert( g >= 0.0 && g <= 1.0 );
|
||||||
|
assert( b >= 0.0 && b <= 1.0 );
|
||||||
|
assert( a >= 0.0 && a <= 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param aColor is one of KiCad's palette colors.
|
||||||
|
* @see EDA_COLOR_T
|
||||||
|
*/
|
||||||
|
COLOR4D( EDA_COLOR_T aColor );
|
||||||
|
|
||||||
|
#ifdef WX_COMPATIBILITY
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param aColor is the color type used by wxWidgets.
|
||||||
|
*/
|
||||||
|
COLOR4D( const wxColour& aColor );
|
||||||
|
#endif /* WX_COMPATIBLITY */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Brighten
|
||||||
|
* Makes the color brighter by a given factor.
|
||||||
|
* @param aFactor Specifies how bright the color should become (valid values: 0.0 .. 1.0).
|
||||||
|
* @return COLOR4D& Brightened color.
|
||||||
|
*/
|
||||||
|
COLOR4D& Brighten( double aFactor )
|
||||||
|
{
|
||||||
|
assert( aFactor >= 0.0 && aFactor <= 1.0 );
|
||||||
|
|
||||||
|
r = r * ( 1.0 - aFactor ) + aFactor;
|
||||||
|
g = g * ( 1.0 - aFactor ) + aFactor;
|
||||||
|
b = b * ( 1.0 - aFactor ) + aFactor;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Darken
|
||||||
|
* Makes the color darker by a given factor.
|
||||||
|
* @param aFactor Specifies how dark the color should become (valid values: 0.0 .. 1.0).
|
||||||
|
* @return COLOR4D& Darkened color.
|
||||||
|
*/
|
||||||
|
COLOR4D& Darken( double aFactor )
|
||||||
|
{
|
||||||
|
assert( aFactor >= 0.0 && aFactor <= 1.0 );
|
||||||
|
|
||||||
|
r = r * ( 1.0 - aFactor );
|
||||||
|
g = g * ( 1.0 - aFactor );
|
||||||
|
b = b * ( 1.0 - aFactor );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Invert
|
||||||
|
* Makes the color inverted, alpha remains the same.
|
||||||
|
* @return COLOR4D& Inverted color.
|
||||||
|
*/
|
||||||
|
COLOR4D& Invert()
|
||||||
|
{
|
||||||
|
r = ( 1.0 - r );
|
||||||
|
g = ( 1.0 - g );
|
||||||
|
b = ( 1.0 - b );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saturates the color to a given factor (in HSV model)
|
||||||
|
*/
|
||||||
|
COLOR4D& Saturate( double aFactor );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Brightened
|
||||||
|
* Returns a color that is brighter by a given factor, without modifying object.
|
||||||
|
* @param aFactor Specifies how bright the color should become (valid values: 0.0 .. 1.0).
|
||||||
|
* @return COLOR4D Highlightedd color.
|
||||||
|
*/
|
||||||
|
COLOR4D Brightened( double aFactor ) const
|
||||||
|
{
|
||||||
|
assert( aFactor >= 0.0 && aFactor <= 1.0 );
|
||||||
|
|
||||||
|
return COLOR4D( r * ( 1.0 - aFactor ) + aFactor,
|
||||||
|
g * ( 1.0 - aFactor ) + aFactor,
|
||||||
|
b * ( 1.0 - aFactor ) + aFactor,
|
||||||
|
a );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Darkened
|
||||||
|
* Returns a color that is darker by a given factor, without modifying object.
|
||||||
|
* @param aFactor Specifies how dark the color should become (valid values: 0.0 .. 1.0).
|
||||||
|
* @return COLOR4D Darkened color.
|
||||||
|
*/
|
||||||
|
COLOR4D Darkened( double aFactor ) const
|
||||||
|
{
|
||||||
|
assert( aFactor >= 0.0 && aFactor <= 1.0 );
|
||||||
|
|
||||||
|
return COLOR4D( r * ( 1.0 - aFactor ),
|
||||||
|
g * ( 1.0 - aFactor ),
|
||||||
|
b * ( 1.0 - aFactor ),
|
||||||
|
a );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Inverted
|
||||||
|
* Returns an inverted color, alpha remains the same.
|
||||||
|
* @return COLOR4D& Inverted color.
|
||||||
|
*/
|
||||||
|
COLOR4D Inverted() const
|
||||||
|
{
|
||||||
|
return COLOR4D( 1.0 - r, 1.0 - g, 1.0 - b, a );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetBrightness
|
||||||
|
* Returns the brightness value of the color ranged from 0.0 to 1.0.
|
||||||
|
* @return The brightness value.
|
||||||
|
*/
|
||||||
|
double GetBrightness() const
|
||||||
|
{
|
||||||
|
// Weighted W3C formula
|
||||||
|
return r * 0.299 + g * 0.587 + b * 0.117;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ToHSV()
|
||||||
|
* Converts current color (stored in RGB) to HSV format.
|
||||||
|
*
|
||||||
|
* @param aOutH is conversion result for hue component.
|
||||||
|
* @param aOutS is conversion result for saturation component.
|
||||||
|
* @param aOutV is conversion result for value component.
|
||||||
|
*/
|
||||||
|
void ToHSV( double& aOutH, double& aOutS, double& aOutV ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FromHSV()
|
||||||
|
* Changes currently used color to the one given by hue, saturation and value parameters.
|
||||||
|
*
|
||||||
|
* @param aOutH is hue component.
|
||||||
|
* @param aOutS is saturation component.
|
||||||
|
* @param aOutV is value component.
|
||||||
|
*/
|
||||||
|
void FromHSV( double aInH, double aInS, double aInV );
|
||||||
|
|
||||||
|
/// @brief Equality operator, are two colors equal
|
||||||
|
const bool operator==( const COLOR4D& aColor );
|
||||||
|
|
||||||
|
/// @brief Not equality operator, are two colors not equal
|
||||||
|
const bool operator!=( const COLOR4D& aColor );
|
||||||
|
|
||||||
|
// Color components: red, green, blue, alpha
|
||||||
|
double r; ///< Red component
|
||||||
|
double g; ///< Green component
|
||||||
|
double b; ///< Blue component
|
||||||
|
double a; ///< Alpha component
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* COLOR4D_H_ */
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file compositor.h
|
||||||
|
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
|
||||||
|
* later compositing into a single image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMPOSITOR_H_
|
||||||
|
#define COMPOSITOR_H_
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
|
||||||
|
class COMPOSITOR
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~COMPOSITOR()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Reset()
|
||||||
|
* performs primary initialiation, necessary to use the object.
|
||||||
|
*/
|
||||||
|
virtual void Initialize() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Resize()
|
||||||
|
* clears the state of COMPOSITOR, so it has to be reinitialized again with the new dimensions.
|
||||||
|
*
|
||||||
|
* @param aWidth is the framebuffer width (in pixels).
|
||||||
|
* @param aHeight is the framebuffer height (in pixels).
|
||||||
|
*/
|
||||||
|
virtual void Resize( unsigned int aWidth, unsigned int aHeight ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function CreateBuffer()
|
||||||
|
* prepares a new buffer that may be used as a rendering target.
|
||||||
|
*
|
||||||
|
* @return is the handle of the buffer. In case of failure 0 (zero) is returned as the handle.
|
||||||
|
*/
|
||||||
|
virtual unsigned int CreateBuffer() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetBuffer()
|
||||||
|
* returns currently used buffer handle.
|
||||||
|
*
|
||||||
|
* @return Currently used buffer handle.
|
||||||
|
*/
|
||||||
|
virtual unsigned int GetBuffer() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetBuffer()
|
||||||
|
* sets the selected buffer as the rendering target. All the following drawing functions are
|
||||||
|
* going to be rendered in the selected buffer.
|
||||||
|
*
|
||||||
|
* @param aBufferHandle is the handle of the buffer or 0 in case of rendering directly to the
|
||||||
|
* display.
|
||||||
|
*/
|
||||||
|
virtual void SetBuffer( unsigned int aBufferHandle ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ClearBuffer()
|
||||||
|
* clears the selected buffer (set by the SetBuffer() function).
|
||||||
|
*/
|
||||||
|
virtual void ClearBuffer() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function DrawBuffer()
|
||||||
|
* draws the selected buffer on the screen.
|
||||||
|
*
|
||||||
|
* @param aBufferHandle is the handle of the buffer to be drawn.
|
||||||
|
*/
|
||||||
|
virtual void DrawBuffer( unsigned int aBufferHandle ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
unsigned int m_width; ///< Width of the buffer (in pixels)
|
||||||
|
unsigned int m_height; ///< Height of the buffer (in pixels)
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* COMPOSITOR_H_ */
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Macro definitions
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEFINITIONS_H_
|
||||||
|
#define DEFINITIONS_H_
|
||||||
|
|
||||||
|
/// Swap the variables if a condition is met.
|
||||||
|
#define SWAP( varA, condition, varB ) if( varA condition varB ) { double tmp = varA; varA = varB; \
|
||||||
|
varB = tmp; }
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* RENDER_TARGET: Possible rendering targets
|
||||||
|
*/
|
||||||
|
enum RENDER_TARGET
|
||||||
|
{
|
||||||
|
TARGET_CACHED = 0, ///< Main rendering target (cached)
|
||||||
|
TARGET_NONCACHED, ///< Auxiliary rendering target (noncached)
|
||||||
|
TARGET_OVERLAY, ///< Items that may change while the view stays the same (noncached)
|
||||||
|
TARGETS_NUMBER ///< Number of available rendering targets
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* DEFINITIONS_H_ */
|
|
@ -0,0 +1,896 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICSABSTRACTIONLAYER_H_
|
||||||
|
#define GRAPHICSABSTRACTIONLAYER_H_
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <stack>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <wx/event.h>
|
||||||
|
|
||||||
|
#include <math/matrix3x3.h>
|
||||||
|
|
||||||
|
#include <gal/color4d.h>
|
||||||
|
#include <gal/definitions.h>
|
||||||
|
#include <gal/stroke_font.h>
|
||||||
|
#include <newstroke_font.h>
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* GridStyle: Type definition of the grid style
|
||||||
|
*/
|
||||||
|
enum GRID_STYLE
|
||||||
|
{
|
||||||
|
GRID_STYLE_LINES, ///< Use lines for the grid
|
||||||
|
GRID_STYLE_DOTS ///< Use dots for the grid
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class GAL is the abstract interface for drawing on a 2D-surface.
|
||||||
|
*
|
||||||
|
* The functions are optimized for drawing shapes of an EDA-program such as KiCad. Most methods
|
||||||
|
* are abstract and need to be implemented by a lower layer, for example by a cairo or OpenGL implementation.
|
||||||
|
* <br>
|
||||||
|
* Almost all methods use world coordinates as arguments. The board design is defined in world space units;
|
||||||
|
* for drawing purposes these are transformed to screen units with this layer. So zooming is handled here as well.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class GAL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor / Destructor
|
||||||
|
GAL();
|
||||||
|
virtual ~GAL();
|
||||||
|
|
||||||
|
// ---------------
|
||||||
|
// Drawing methods
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
/// @brief Begin the drawing, needs to be called for every new frame.
|
||||||
|
virtual void BeginDrawing() = 0;
|
||||||
|
|
||||||
|
/// @brief End the drawing, needs to be called for every new frame.
|
||||||
|
virtual void EndDrawing() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a line.
|
||||||
|
*
|
||||||
|
* Start and end points are defined as 2D-Vectors.
|
||||||
|
*
|
||||||
|
* @param aStartPoint is the start point of the line.
|
||||||
|
* @param aEndPoint is the end point of the line.
|
||||||
|
*/
|
||||||
|
virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a rounded segment.
|
||||||
|
*
|
||||||
|
* Start and end points are defined as 2D-Vectors.
|
||||||
|
*
|
||||||
|
* @param aStartPoint is the start point of the segment.
|
||||||
|
* @param aEndPoint is the end point of the segment.
|
||||||
|
* @param aWidth is a width of the segment
|
||||||
|
*/
|
||||||
|
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a polyline
|
||||||
|
*
|
||||||
|
* @param aPointList is a list of 2D-Vectors containing the polyline points.
|
||||||
|
*/
|
||||||
|
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a circle using world coordinates.
|
||||||
|
*
|
||||||
|
* @param aCenterPoint is the center point of the circle.
|
||||||
|
* @param aRadius is the radius of the circle.
|
||||||
|
*/
|
||||||
|
virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw an arc.
|
||||||
|
*
|
||||||
|
* @param aCenterPoint is the center point of the arc.
|
||||||
|
* @param aRadius is the arc radius.
|
||||||
|
* @param aStartAngle is the start angle of the arc.
|
||||||
|
* @param aEndAngle is the end angle of the arc.
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a rectangle.
|
||||||
|
*
|
||||||
|
* @param aStartPoint is the start point of the rectangle.
|
||||||
|
* @param aEndPoint is the end point of the rectangle.
|
||||||
|
*/
|
||||||
|
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a polygon.
|
||||||
|
*
|
||||||
|
* @param aPointList is the list of the polygon points.
|
||||||
|
*/
|
||||||
|
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a cubic bezier spline.
|
||||||
|
*
|
||||||
|
* @param startPoint is the start point of the spline.
|
||||||
|
* @param controlPointA is the first control point.
|
||||||
|
* @param controlPointB is the second control point.
|
||||||
|
* @param endPoint is the end point of the spline.
|
||||||
|
*/
|
||||||
|
virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||||
|
const VECTOR2D& controlPointB, const VECTOR2D& endPoint ) = 0;
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Screen methods
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
/// @brief Resizes the canvas.
|
||||||
|
virtual void ResizeScreen( int aWidth, int aHeight ) = 0;
|
||||||
|
|
||||||
|
/// @brief Shows/hides the GAL canvas
|
||||||
|
virtual bool Show( bool aShow ) = 0;
|
||||||
|
|
||||||
|
/// @brief Returns GAL canvas size in pixels
|
||||||
|
VECTOR2D GetScreenPixelSize() const
|
||||||
|
{
|
||||||
|
return screenSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Force all remaining objects to be drawn.
|
||||||
|
virtual void Flush() = 0;
|
||||||
|
|
||||||
|
/// @brief Clear the screen.
|
||||||
|
virtual void ClearScreen() = 0;
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
// Attribute setting
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable/disable fill.
|
||||||
|
*
|
||||||
|
* @param aIsFillEnabled is true, when the graphics objects should be filled, else false.
|
||||||
|
*/
|
||||||
|
inline virtual void SetIsFill( bool aIsFillEnabled )
|
||||||
|
{
|
||||||
|
isFillEnabled = aIsFillEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable/disable stroked outlines.
|
||||||
|
*
|
||||||
|
* @param aIsStrokeEnabled is true, if the outline of an object should be stroked.
|
||||||
|
*/
|
||||||
|
inline virtual void SetIsStroke( bool aIsStrokeEnabled )
|
||||||
|
{
|
||||||
|
isStrokeEnabled = aIsStrokeEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the fill color.
|
||||||
|
*
|
||||||
|
* @param aColor is the color for filling.
|
||||||
|
*/
|
||||||
|
inline virtual void SetFillColor( const COLOR4D& aColor )
|
||||||
|
{
|
||||||
|
fillColor = aColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the stroke color.
|
||||||
|
*
|
||||||
|
* @param aColor is the color for stroking the outline.
|
||||||
|
*/
|
||||||
|
inline virtual void SetStrokeColor( const COLOR4D& aColor )
|
||||||
|
{
|
||||||
|
strokeColor = aColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the stroke color.
|
||||||
|
*
|
||||||
|
* @return the color for stroking the outline.
|
||||||
|
*/
|
||||||
|
inline COLOR4D GetStrokeColor()
|
||||||
|
{
|
||||||
|
return strokeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the background color.
|
||||||
|
*
|
||||||
|
* @param aColor is the color for background filling.
|
||||||
|
*/
|
||||||
|
inline virtual void SetBackgroundColor( const COLOR4D& aColor )
|
||||||
|
{
|
||||||
|
backgroundColor = aColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the line width.
|
||||||
|
*
|
||||||
|
* @param aLineWidth is the line width.
|
||||||
|
*/
|
||||||
|
inline virtual void SetLineWidth( double aLineWidth )
|
||||||
|
{
|
||||||
|
lineWidth = aLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the line width.
|
||||||
|
*
|
||||||
|
* @return the actual line width.
|
||||||
|
*/
|
||||||
|
inline double GetLineWidth()
|
||||||
|
{
|
||||||
|
return lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the depth of the layer (position on the z-axis)
|
||||||
|
*
|
||||||
|
* @param aLayerDepth the layer depth for the objects.
|
||||||
|
*/
|
||||||
|
inline virtual void SetLayerDepth( double aLayerDepth )
|
||||||
|
{
|
||||||
|
layerDepth = aLayerDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
// Text
|
||||||
|
// ----
|
||||||
|
/**
|
||||||
|
* @brief Draws a vector type text using preloaded Newstroke font.
|
||||||
|
*
|
||||||
|
* @param aText is the text to be drawn.
|
||||||
|
* @param aPosition is the text position in world coordinates.
|
||||||
|
* @param aRotationAngle is the text rotation angle.
|
||||||
|
*/
|
||||||
|
inline virtual void StrokeText( const std::string& aText, const VECTOR2D& aPosition,
|
||||||
|
double aRotationAngle )
|
||||||
|
{
|
||||||
|
strokeFont.Draw( aText, aPosition, aRotationAngle );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads attributes of the given text (bold/italic/underline/mirrored and so on).
|
||||||
|
*
|
||||||
|
* @param aText is the text item.
|
||||||
|
*/
|
||||||
|
virtual void SetTextAttributes( const EDA_TEXT* aText );
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetGlyphSize()
|
||||||
|
inline void SetGlyphSize( const VECTOR2D aGlyphSize )
|
||||||
|
{
|
||||||
|
strokeFont.SetGlyphSize( aGlyphSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetBold()
|
||||||
|
inline void SetBold( const bool aBold )
|
||||||
|
{
|
||||||
|
strokeFont.SetBold( aBold );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetItalic()
|
||||||
|
inline void SetItalic( const bool aItalic )
|
||||||
|
{
|
||||||
|
strokeFont.SetItalic( aItalic );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetMirrored()
|
||||||
|
inline void SetMirrored( const bool aMirrored )
|
||||||
|
{
|
||||||
|
strokeFont.SetMirrored( aMirrored );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetHorizontalJustify()
|
||||||
|
inline void SetHorizontalJustify( const EDA_TEXT_HJUSTIFY_T aHorizontalJustify )
|
||||||
|
{
|
||||||
|
strokeFont.SetHorizontalJustify( aHorizontalJustify );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @copydoc STROKE_FONT::SetVerticalJustify()
|
||||||
|
inline void SetVerticalJustify( const EDA_TEXT_VJUSTIFY_T aVerticalJustify )
|
||||||
|
{
|
||||||
|
strokeFont.SetVerticalJustify( aVerticalJustify );
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Transformation
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transform the context.
|
||||||
|
*
|
||||||
|
* @param aTransformation is the ransformation matrix.
|
||||||
|
*/
|
||||||
|
virtual void Transform( MATRIX3x3D aTransformation ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Rotate the context.
|
||||||
|
*
|
||||||
|
* @param aAngle is the rotation angle in radians.
|
||||||
|
*/
|
||||||
|
virtual void Rotate( double aAngle ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Translate the context.
|
||||||
|
*
|
||||||
|
* @param aTranslation is the translation vector.
|
||||||
|
*/
|
||||||
|
virtual void Translate( const VECTOR2D& aTranslation ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Scale the context.
|
||||||
|
*
|
||||||
|
* @param aScale is the scale factor for the x- and y-axis.
|
||||||
|
*/
|
||||||
|
virtual void Scale( const VECTOR2D& aScale ) = 0;
|
||||||
|
|
||||||
|
/// @brief Save the context.
|
||||||
|
virtual void Save() = 0;
|
||||||
|
|
||||||
|
/// @brief Restore the context.
|
||||||
|
virtual void Restore() = 0;
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// Group methods
|
||||||
|
// ---------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Begin a group.
|
||||||
|
*
|
||||||
|
* A group is a collection of graphic items.
|
||||||
|
* Hierarchical groups are possible, attributes and transformations can be used.
|
||||||
|
*
|
||||||
|
* @return the number of the group.
|
||||||
|
*/
|
||||||
|
virtual int BeginGroup() = 0;
|
||||||
|
|
||||||
|
/// @brief End the group.
|
||||||
|
virtual void EndGroup() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw the stored group.
|
||||||
|
*
|
||||||
|
* @param aGroupNumber is the group number.
|
||||||
|
*/
|
||||||
|
virtual void DrawGroup( int aGroupNumber ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the color used to draw the group.
|
||||||
|
*
|
||||||
|
* @param aGroupNumber is the group number.
|
||||||
|
* @param aNewColor is the new color.
|
||||||
|
*/
|
||||||
|
virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the depth (Z-axis position) of the group.
|
||||||
|
*
|
||||||
|
* @param aGroupNumber is the group number.
|
||||||
|
* @param aDepth is the new depth.
|
||||||
|
*/
|
||||||
|
virtual void ChangeGroupDepth( int aGroupNumber, int aDepth ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete the group from the memory.
|
||||||
|
*
|
||||||
|
* @param aGroupNumber is the group number.
|
||||||
|
*/
|
||||||
|
virtual void DeleteGroup( int aGroupNumber ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete all data created during caching of graphic items.
|
||||||
|
*/
|
||||||
|
virtual void ClearCache() = 0;
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Handling the world <-> screen transformation
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
/// @brief Compute the world <-> screen transformation matrix
|
||||||
|
virtual void ComputeWorldScreenMatrix();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the world <-> screen transformation matrix.
|
||||||
|
*
|
||||||
|
* @return the transformation matrix.
|
||||||
|
*/
|
||||||
|
MATRIX3x3D GetWorldScreenMatrix()
|
||||||
|
{
|
||||||
|
return worldScreenMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the world <-> screen transformation matrix.
|
||||||
|
*
|
||||||
|
* @param aMatrix is the 3x3 world <-> screen transformation matrix.
|
||||||
|
*/
|
||||||
|
inline void SetWorldScreenMatrix( const MATRIX3x3D& aMatrix )
|
||||||
|
{
|
||||||
|
worldScreenMatrix = aMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the unit length.
|
||||||
|
*
|
||||||
|
* This defines the length [inch] per one integer. For instance a value 0.001 means
|
||||||
|
* that the coordinate [1000, 1000] corresponds with a point at (1 inch, 1 inch) or
|
||||||
|
* 1 mil resolution per integer.
|
||||||
|
*
|
||||||
|
* @param aWorldUnitLength is the world Unit length.
|
||||||
|
*/
|
||||||
|
inline void SetWorldUnitLength( double aWorldUnitLength )
|
||||||
|
{
|
||||||
|
worldUnitLength = aWorldUnitLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the dots per inch of the screen.
|
||||||
|
*
|
||||||
|
* This value depends on the user screen, it should be configurable by the application.
|
||||||
|
* For instance a typical notebook with HD+ resolution (1600x900) has 106 DPI.
|
||||||
|
*
|
||||||
|
* @param aScreenDPI are the screen DPI.
|
||||||
|
*/
|
||||||
|
inline void SetScreenDPI( double aScreenDPI )
|
||||||
|
{
|
||||||
|
screenDPI = aScreenDPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the Point in world space to look at.
|
||||||
|
*
|
||||||
|
* This point corresponds with the center of the actual drawing area.
|
||||||
|
*
|
||||||
|
* @param aPoint is the look at point (center of the actual drawing area).
|
||||||
|
*/
|
||||||
|
inline void SetLookAtPoint( const VECTOR2D& aPoint )
|
||||||
|
{
|
||||||
|
lookAtPoint = aPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the look at point.
|
||||||
|
*
|
||||||
|
* @return the look at point.
|
||||||
|
*/
|
||||||
|
inline VECTOR2D GetLookAtPoint()
|
||||||
|
{
|
||||||
|
return lookAtPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the zoom factor of the scene.
|
||||||
|
*
|
||||||
|
* @param aZoomFactor is the zoom factor.
|
||||||
|
*/
|
||||||
|
inline void SetZoomFactor( double aZoomFactor )
|
||||||
|
{
|
||||||
|
zoomFactor = aZoomFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the zoom factor
|
||||||
|
*
|
||||||
|
* @return the zoom factor.
|
||||||
|
*/
|
||||||
|
inline double GetZoomFactor()
|
||||||
|
{
|
||||||
|
return zoomFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the range of the layer depth.
|
||||||
|
*
|
||||||
|
* Usually required for the OpenGL implementation, any object outside this range is not drawn.
|
||||||
|
*
|
||||||
|
* @param aDepthRange is the depth range where component x is the near clipping plane and y
|
||||||
|
* is the far clipping plane.
|
||||||
|
*/
|
||||||
|
inline void SetDepthRange( const VECTOR2D& aDepthRange )
|
||||||
|
{
|
||||||
|
depthRange = aDepthRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the minimum depth in the currently used range (the top).
|
||||||
|
*/
|
||||||
|
inline double GetMinDepth()
|
||||||
|
{
|
||||||
|
return depthRange.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the maximum depth in the currently used range (the bottom).
|
||||||
|
*/
|
||||||
|
inline double GetMaxDepth()
|
||||||
|
{
|
||||||
|
return depthRange.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the world scale.
|
||||||
|
*
|
||||||
|
* @return the actual world scale factor.
|
||||||
|
*/
|
||||||
|
inline double GetWorldScale()
|
||||||
|
{
|
||||||
|
return worldScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets flipping of the screen.
|
||||||
|
*
|
||||||
|
* @param xAxis is the flip flag for the X axis.
|
||||||
|
* @param yAxis is the flip flag for the Y axis.
|
||||||
|
*/
|
||||||
|
inline void SetFlip( bool xAxis, bool yAxis )
|
||||||
|
{
|
||||||
|
if( xAxis )
|
||||||
|
flipX = -1.0; // flipped
|
||||||
|
else
|
||||||
|
flipX = 1.0; // regular
|
||||||
|
|
||||||
|
if( yAxis )
|
||||||
|
flipY = -1.0; // flipped
|
||||||
|
else
|
||||||
|
flipY = 1.0; // regular
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// Buffer manipulation methods
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Save the screen contents.
|
||||||
|
*/
|
||||||
|
virtual void SaveScreen() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore the screen contents.
|
||||||
|
*/
|
||||||
|
virtual void RestoreScreen() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the target for rendering.
|
||||||
|
*
|
||||||
|
* @param aTarget is the new target for rendering.
|
||||||
|
*/
|
||||||
|
virtual void SetTarget( RENDER_TARGET aTarget ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the currently used target for rendering.
|
||||||
|
*
|
||||||
|
* @return The current rendering target.
|
||||||
|
*/
|
||||||
|
virtual RENDER_TARGET GetTarget() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the target for rendering.
|
||||||
|
*
|
||||||
|
* @param aTarget is the target to be cleared.
|
||||||
|
*/
|
||||||
|
virtual void ClearTarget( RENDER_TARGET aTarget ) = 0;
|
||||||
|
|
||||||
|
// -------------
|
||||||
|
// Grid methods
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the visibility setting of the grid.
|
||||||
|
*
|
||||||
|
* @param aVisibility is the new visibility setting of the grid.
|
||||||
|
*/
|
||||||
|
inline void SetGridVisibility( bool aVisibility )
|
||||||
|
{
|
||||||
|
gridVisibility = aVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the origin point for the grid.
|
||||||
|
*
|
||||||
|
* @param aGridOrigin is a vector containing the grid origin point, in world coordinates.
|
||||||
|
*/
|
||||||
|
inline void SetGridOrigin( const VECTOR2D& aGridOrigin )
|
||||||
|
{
|
||||||
|
gridOrigin = aGridOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the screen size of the grid origin marker
|
||||||
|
*
|
||||||
|
* @param aSize is the radius of the origin marker, in pixels.
|
||||||
|
*/
|
||||||
|
inline void SetGridOriginMarkerSize( int aSize )
|
||||||
|
{
|
||||||
|
gridOriginMarkerSize = aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the threshold for grid drawing.
|
||||||
|
*
|
||||||
|
* @param aThreshold is the minimum grid cell size (in pixels) for which the grid is drawn.
|
||||||
|
*/
|
||||||
|
inline void SetGridDrawThreshold( int aThreshold )
|
||||||
|
{
|
||||||
|
gridDrawThreshold = aThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the grid size.
|
||||||
|
*
|
||||||
|
* @param aGridSize is a vector containing the grid size in x and y direction.
|
||||||
|
*/
|
||||||
|
inline void SetGridSize( const VECTOR2D& aGridSize )
|
||||||
|
{
|
||||||
|
gridSize = aGridSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the grid size.
|
||||||
|
*
|
||||||
|
* @return A vector containing the grid size in x and y direction.
|
||||||
|
*/
|
||||||
|
inline const VECTOR2D& GetGridSize() const
|
||||||
|
{
|
||||||
|
return gridSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the grid color.
|
||||||
|
*
|
||||||
|
* @param aGridColor is the grid color, it should have a low alpha value for the best effect.
|
||||||
|
*/
|
||||||
|
inline void SetGridColor( const COLOR4D& aGridColor )
|
||||||
|
{
|
||||||
|
gridColor = aGridColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw every tick line wider.
|
||||||
|
*
|
||||||
|
* @param aInterval increase the width of every aInterval line, if 0 do not use this feature.
|
||||||
|
*/
|
||||||
|
inline void SetCoarseGrid( int aInterval )
|
||||||
|
{
|
||||||
|
gridTick = aInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the grid line width.
|
||||||
|
*
|
||||||
|
* @return the grid line width
|
||||||
|
*/
|
||||||
|
inline double GetGridLineWidth()
|
||||||
|
{
|
||||||
|
return gridLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the grid line width.
|
||||||
|
*
|
||||||
|
* @param aGridLineWidth is the rid line width.
|
||||||
|
*/
|
||||||
|
inline void SetGridLineWidth( double aGridLineWidth )
|
||||||
|
{
|
||||||
|
gridLineWidth = aGridLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Draw the grid
|
||||||
|
void DrawGrid();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetGridPoint()
|
||||||
|
* For a given point it returns the nearest point belonging to the grid.
|
||||||
|
*
|
||||||
|
* @param aPoint is the point for which the grid point is searched.
|
||||||
|
* @return The nearest grid point.
|
||||||
|
*/
|
||||||
|
VECTOR2D GetGridPoint( VECTOR2D aPoint ) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Change the grid display style.
|
||||||
|
*
|
||||||
|
* @param aGridStyle is the new style for grid.
|
||||||
|
*/
|
||||||
|
inline virtual void SetGridStyle( GRID_STYLE aGridStyle )
|
||||||
|
{
|
||||||
|
gridStyle = aGridStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute the point position in world coordinates from given screen coordinates.
|
||||||
|
*
|
||||||
|
* @param aPoint the pointposition in screen coordinates.
|
||||||
|
* @return the point position in world coordinates.
|
||||||
|
*/
|
||||||
|
inline virtual VECTOR2D ToWorld( const VECTOR2D& aPoint ) const
|
||||||
|
{
|
||||||
|
return VECTOR2D( screenWorldMatrix * aPoint );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute the point position in screen coordinates from given world coordinates.
|
||||||
|
*
|
||||||
|
* @param aPoint the pointposition in world coordinates.
|
||||||
|
* @return the point position in screen coordinates.
|
||||||
|
*/
|
||||||
|
inline virtual VECTOR2D ToScreen( const VECTOR2D& aPoint ) const
|
||||||
|
{
|
||||||
|
return VECTOR2D( worldScreenMatrix * aPoint );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable/Disable cursor.
|
||||||
|
*
|
||||||
|
* @param aIsCursorEnabled is true if the cursor should be enabled, else false.
|
||||||
|
*/
|
||||||
|
inline void SetCursorEnabled( bool aCursorEnabled )
|
||||||
|
{
|
||||||
|
isCursorEnabled = aCursorEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the cursor color.
|
||||||
|
*
|
||||||
|
* @param aCursorColor is the color of the cursor.
|
||||||
|
*/
|
||||||
|
inline void SetCursorColor( const COLOR4D& aCursorColor )
|
||||||
|
{
|
||||||
|
cursorColor = aCursorColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the cursor size.
|
||||||
|
*
|
||||||
|
* @param aCursorSize is the size of the cursor.
|
||||||
|
*/
|
||||||
|
inline void SetCursorSize( unsigned int aCursorSize )
|
||||||
|
{
|
||||||
|
cursorSize = aCursorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw the cursor.
|
||||||
|
*
|
||||||
|
* @param aCursorPosition is the cursor position in screen coordinates.
|
||||||
|
*/
|
||||||
|
virtual void DrawCursor( const VECTOR2D& aCursorPosition ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Changes the current depth to deeper, so it is possible to draw objects right beneath
|
||||||
|
* other.
|
||||||
|
*/
|
||||||
|
inline void AdvanceDepth()
|
||||||
|
{
|
||||||
|
layerDepth -= 0.001;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores current drawing depth on the depth stack.
|
||||||
|
*/
|
||||||
|
inline void PushDepth()
|
||||||
|
{
|
||||||
|
depthStack.push( layerDepth );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restores previously stored drawing depth for the depth stack.
|
||||||
|
*/
|
||||||
|
inline void PopDepth()
|
||||||
|
{
|
||||||
|
layerDepth = depthStack.top();
|
||||||
|
depthStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Depth level on which the grid is drawn
|
||||||
|
static const int GRID_DEPTH = 1024;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::stack<double> depthStack; ///< Stored depth values
|
||||||
|
VECTOR2D screenSize; ///< Screen size in screen coordinates
|
||||||
|
|
||||||
|
double worldUnitLength; ///< The unit length of the world coordinates [inch]
|
||||||
|
double screenDPI; ///< The dots per inch of the screen
|
||||||
|
VECTOR2D lookAtPoint; ///< Point to be looked at in world space
|
||||||
|
|
||||||
|
double zoomFactor; ///< The zoom factor
|
||||||
|
MATRIX3x3D worldScreenMatrix; ///< World transformation
|
||||||
|
MATRIX3x3D screenWorldMatrix; ///< Screen transformation
|
||||||
|
double worldScale; ///< The scale factor world->screen
|
||||||
|
double flipX; ///< Flag for X axis flipping
|
||||||
|
double flipY; ///< Flag for Y axis flipping
|
||||||
|
|
||||||
|
double lineWidth; ///< The line width
|
||||||
|
|
||||||
|
bool isFillEnabled; ///< Is filling of graphic objects enabled ?
|
||||||
|
bool isStrokeEnabled; ///< Are the outlines stroked ?
|
||||||
|
|
||||||
|
COLOR4D backgroundColor; ///< The background color
|
||||||
|
COLOR4D fillColor; ///< The fill color
|
||||||
|
COLOR4D strokeColor; ///< The color of the outlines
|
||||||
|
|
||||||
|
double layerDepth; ///< The actual layer depth
|
||||||
|
VECTOR2D depthRange; ///< Range of the depth
|
||||||
|
|
||||||
|
// Grid settings
|
||||||
|
bool gridVisibility; ///< Should the grid be shown
|
||||||
|
GRID_STYLE gridStyle; ///< Grid display style
|
||||||
|
VECTOR2D gridSize; ///< The grid size
|
||||||
|
VECTOR2D gridOrigin; ///< The grid origin
|
||||||
|
COLOR4D gridColor; ///< Color of the grid
|
||||||
|
int gridTick; ///< Every tick line gets the double width
|
||||||
|
double gridLineWidth; ///< Line width of the grid
|
||||||
|
int gridDrawThreshold; ///< Minimum screen size of the grid (pixels)
|
||||||
|
///< below which the grid is not drawn
|
||||||
|
int gridOriginMarkerSize; ///< Grid origin indicator size (pixels)
|
||||||
|
|
||||||
|
bool isCursorEnabled; ///< Is the cursor enabled?
|
||||||
|
COLOR4D cursorColor; ///< Cursor color
|
||||||
|
int cursorSize; ///< Size of the cursor in pixels
|
||||||
|
|
||||||
|
/// Instance of object that stores information about how to draw texts
|
||||||
|
STROKE_FONT strokeFont;
|
||||||
|
|
||||||
|
/// Compute the scaling factor for the world->screen matrix
|
||||||
|
inline void ComputeWorldScale()
|
||||||
|
{
|
||||||
|
worldScale = screenDPI * worldUnitLength * zoomFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a grid line (usually a simplified line function).
|
||||||
|
*
|
||||||
|
* @param aStartPoint is the start point of the line.
|
||||||
|
* @param aEndPoint is the end point of the line.
|
||||||
|
*/
|
||||||
|
virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the cursor.
|
||||||
|
*
|
||||||
|
* @param aCursorSize is the size of the cursor.
|
||||||
|
*/
|
||||||
|
virtual void initCursor( int aCursorSize ) = 0;
|
||||||
|
|
||||||
|
static const int MIN_DEPTH = -2048;
|
||||||
|
static const int MAX_DEPTH = 2047;
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* GRAPHICSABSTRACTIONLAYER_H_ */
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 CERN
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file cached_container.h
|
||||||
|
* @brief Class to store instances of VERTEX with caching. It allows storing VERTEX objects and
|
||||||
|
* associates them with VERTEX_ITEMs. This leads to a possibility of caching vertices data in the
|
||||||
|
* GPU memory and a fast reuse of that data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CACHED_CONTAINER_H_
|
||||||
|
#define CACHED_CONTAINER_H_
|
||||||
|
|
||||||
|
#include <gal/opengl/vertex_container.h>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
// Debug messages verbosity level
|
||||||
|
// #define CACHED_CONTAINER_TEST 1
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
class VERTEX_ITEM;
|
||||||
|
class SHADER;
|
||||||
|
|
||||||
|
class CACHED_CONTAINER : public VERTEX_CONTAINER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CACHED_CONTAINER( unsigned int aSize = defaultInitSize );
|
||||||
|
|
||||||
|
///> @copydoc VERTEX_CONTAINER::SetItem()
|
||||||
|
virtual void SetItem( VERTEX_ITEM* aItem );
|
||||||
|
|
||||||
|
///> @copydoc VERTEX_CONTAINER::FinishItem()
|
||||||
|
virtual void FinishItem();
|
||||||
|
|
||||||
|
///> @copydoc VERTEX_CONTAINER::Allocate()
|
||||||
|
virtual VERTEX* Allocate( unsigned int aSize );
|
||||||
|
|
||||||
|
///> @copydoc VERTEX_CONTAINER::Delete()
|
||||||
|
virtual void Delete( VERTEX_ITEM* aItem );
|
||||||
|
|
||||||
|
///> @copydoc VERTEX_CONTAINER::Clear()
|
||||||
|
virtual void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetVertices()
|
||||||
|
* returns the vertices stored by the specific item.
|
||||||
|
*
|
||||||
|
* @param aItem is the item.
|
||||||
|
*/
|
||||||
|
virtual VERTEX* GetVertices( const VERTEX_ITEM* aItem ) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///> Maps size of free memory chunks to their offsets
|
||||||
|
typedef std::pair<unsigned int, unsigned int> CHUNK;
|
||||||
|
typedef std::multimap<unsigned int, unsigned int> FREE_CHUNK_MAP;
|
||||||
|
|
||||||
|
/// List of all the stored items
|
||||||
|
typedef std::set<VERTEX_ITEM*> ITEMS;
|
||||||
|
|
||||||
|
///> Stores size & offset of free chunks.
|
||||||
|
FREE_CHUNK_MAP m_freeChunks;
|
||||||
|
|
||||||
|
///> Stored VERTEX_ITEMs
|
||||||
|
ITEMS m_items;
|
||||||
|
|
||||||
|
///> Currently modified item
|
||||||
|
VERTEX_ITEM* m_item;
|
||||||
|
|
||||||
|
///> Properties of currently modified chunk & item
|
||||||
|
unsigned int m_chunkSize;
|
||||||
|
unsigned int m_chunkOffset;
|
||||||
|
unsigned int m_itemSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function reallocate()
|
||||||
|
* resizes the chunk that stores the current item to the given size.
|
||||||
|
*
|
||||||
|
* @param aSize is the number of vertices to be stored.
|
||||||
|
* @return offset of the new chunk.
|
||||||
|
*/
|
||||||
|
virtual unsigned int reallocate( unsigned int aSize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function defragment()
|
||||||
|
* removes empty spaces between chunks, so after that there is a long continous space
|
||||||
|
* for storing vertices at the and of the container.
|
||||||
|
*
|
||||||
|
* @param aTarget is the already allocated destination for defragmented data. It has to be
|
||||||
|
* at least of the same size as the current container. If left NULL, it will be allocated
|
||||||
|
* inside the defragment() function.
|
||||||
|
* @return false in case of failure (eg. memory shortage)
|
||||||
|
*/
|
||||||
|
virtual bool defragment( VERTEX* aTarget = NULL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function mergeFreeChunks()
|
||||||
|
* looks for consecutive free memory chunks and merges them, decreasing fragmentation of
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
virtual void mergeFreeChunks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function resizeContainer()
|
||||||
|
*
|
||||||
|
* prepares a bigger container of a given size.
|
||||||
|
* @param aNewSize is the new size of container, expressed in vertices
|
||||||
|
* @return false in case of failure (eg. memory shortage)
|
||||||
|
*/
|
||||||
|
virtual bool resizeContainer( unsigned int aNewSize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function getPowerOf2()
|
||||||
|
* returns the nearest power of 2, bigger than aNumber.
|
||||||
|
*
|
||||||
|
* @param aNumber is the number for which we look for a bigger power of 2.
|
||||||
|
*/
|
||||||
|
unsigned int getPowerOf2( unsigned int aNumber ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Function getChunkSize()
|
||||||
|
* returns size of the given chunk.
|
||||||
|
*
|
||||||
|
* @param aChunk is the chunk.
|
||||||
|
*/
|
||||||
|
inline int getChunkSize( const CHUNK& aChunk ) const
|
||||||
|
{
|
||||||
|
return aChunk.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function getChunkOffset()
|
||||||
|
* returns offset of the chunk.
|
||||||
|
*
|
||||||
|
* @param aChunk is the chunk.
|
||||||
|
*/
|
||||||
|
inline unsigned int getChunkOffset( const CHUNK& aChunk ) const
|
||||||
|
{
|
||||||
|
return aChunk.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Debug & test functions
|
||||||
|
#if CACHED_CONTAINER_TEST > 0
|
||||||
|
void showFreeChunks();
|
||||||
|
void showReservedChunks();
|
||||||
|
void test();
|
||||||
|
#else
|
||||||
|
inline void showFreeChunks() {}
|
||||||
|
inline void showReservedChunks() {}
|
||||||
|
inline void test() {}
|
||||||
|
#endif /* CACHED_CONTAINER_TEST */
|
||||||
|
};
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif /* CACHED_CONTAINER_H_ */
|
|
@ -0,0 +1,475 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// OpenGL Mathematics (glm.g-truc.net)
|
||||||
|
///
|
||||||
|
/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net)
|
||||||
|
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
/// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
/// in the Software without restriction, including without limitation the rights
|
||||||
|
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
/// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
/// furnished to do so, subject to the following conditions:
|
||||||
|
///
|
||||||
|
/// The above copyright notice and this permission notice shall be included in
|
||||||
|
/// all copies or substantial portions of the Software.
|
||||||
|
///
|
||||||
|
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
/// THE SOFTWARE.
|
||||||
|
///
|
||||||
|
/// @ref core
|
||||||
|
/// @file glm/core/_detail.hpp
|
||||||
|
/// @date 2008-07-24 / 2011-06-14
|
||||||
|
/// @author Christophe Riccio
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef glm_core_detail
|
||||||
|
#define glm_core_detail
|
||||||
|
|
||||||
|
#include "setup.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#if(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
|
||||||
|
#include <cstdint>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace glm{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
class half;
|
||||||
|
|
||||||
|
#if(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) // C99 detected, 64 bit types available
|
||||||
|
typedef int64_t sint64;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
#elif(GLM_COMPILER & GLM_COMPILER_VC)
|
||||||
|
typedef signed __int64 sint64;
|
||||||
|
typedef unsigned __int64 uint64;
|
||||||
|
#elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_LLVM_GCC | GLM_COMPILER_CLANG))
|
||||||
|
__extension__ typedef signed long long sint64;
|
||||||
|
__extension__ typedef unsigned long long uint64;
|
||||||
|
#elif(GLM_COMPILER & GLM_COMPILER_BC)
|
||||||
|
typedef Int64 sint64;
|
||||||
|
typedef Uint64 uint64;
|
||||||
|
#else//unknown compiler
|
||||||
|
typedef signed long long sint64;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
#endif//GLM_COMPILER
|
||||||
|
|
||||||
|
template<bool C>
|
||||||
|
struct If
|
||||||
|
{
|
||||||
|
template<typename F, typename T>
|
||||||
|
static GLM_FUNC_QUALIFIER T apply(F functor, const T& val)
|
||||||
|
{
|
||||||
|
return functor(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct If<false>
|
||||||
|
{
|
||||||
|
template<typename F, typename T>
|
||||||
|
static GLM_FUNC_QUALIFIER T apply(F, const T& val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//template <typename T>
|
||||||
|
//struct traits
|
||||||
|
//{
|
||||||
|
// static const bool is_signed = false;
|
||||||
|
// static const bool is_float = false;
|
||||||
|
// static const bool is_vector = false;
|
||||||
|
// static const bool is_matrix = false;
|
||||||
|
// static const bool is_genType = false;
|
||||||
|
// static const bool is_genIType = false;
|
||||||
|
// static const bool is_genUType = false;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <>
|
||||||
|
//struct traits<half>
|
||||||
|
//{
|
||||||
|
// static const bool is_float = true;
|
||||||
|
// static const bool is_genType = true;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <>
|
||||||
|
//struct traits<float>
|
||||||
|
//{
|
||||||
|
// static const bool is_float = true;
|
||||||
|
// static const bool is_genType = true;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <>
|
||||||
|
//struct traits<double>
|
||||||
|
//{
|
||||||
|
// static const bool is_float = true;
|
||||||
|
// static const bool is_genType = true;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <typename genType>
|
||||||
|
//struct desc
|
||||||
|
//{
|
||||||
|
// typedef genType type;
|
||||||
|
// typedef genType * pointer;
|
||||||
|
// typedef genType const* const_pointer;
|
||||||
|
// typedef genType const *const const_pointer_const;
|
||||||
|
// typedef genType *const pointer_const;
|
||||||
|
// typedef genType & reference;
|
||||||
|
// typedef genType const& const_reference;
|
||||||
|
// typedef genType const& param_type;
|
||||||
|
|
||||||
|
// typedef typename genType::value_type value_type;
|
||||||
|
// typedef typename genType::size_type size_type;
|
||||||
|
// static const typename size_type value_size;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <typename genType>
|
||||||
|
//const typename desc<genType>::size_type desc<genType>::value_size = genType::value_size();
|
||||||
|
|
||||||
|
union uif32
|
||||||
|
{
|
||||||
|
GLM_FUNC_QUALIFIER uif32() :
|
||||||
|
i(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER uif32(float f) :
|
||||||
|
f(f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER uif32(unsigned int i) :
|
||||||
|
i(i)
|
||||||
|
{}
|
||||||
|
|
||||||
|
float f;
|
||||||
|
unsigned int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
union uif64
|
||||||
|
{
|
||||||
|
GLM_FUNC_QUALIFIER uif64() :
|
||||||
|
i(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER uif64(double f) :
|
||||||
|
f(f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER uif64(uint64 i) :
|
||||||
|
i(i)
|
||||||
|
{}
|
||||||
|
|
||||||
|
double f;
|
||||||
|
uint64 i;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uif32 uif;
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// int
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_int
|
||||||
|
{
|
||||||
|
enum is_int_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GLM_DETAIL_IS_INT(T) \
|
||||||
|
template <> \
|
||||||
|
struct is_int<T> \
|
||||||
|
{ \
|
||||||
|
enum is_int_enum \
|
||||||
|
{ \
|
||||||
|
_YES = 1, \
|
||||||
|
_NO = 0 \
|
||||||
|
}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// uint
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_uint
|
||||||
|
{
|
||||||
|
enum is_uint_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GLM_DETAIL_IS_UINT(T) \
|
||||||
|
template <> \
|
||||||
|
struct is_uint<T> \
|
||||||
|
{ \
|
||||||
|
enum is_uint_enum \
|
||||||
|
{ \
|
||||||
|
_YES = 1, \
|
||||||
|
_NO = 0 \
|
||||||
|
}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
//GLM_DETAIL_IS_UINT(unsigned long long)
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// float
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_float
|
||||||
|
{
|
||||||
|
enum is_float_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GLM_DETAIL_IS_FLOAT(T) \
|
||||||
|
template <> \
|
||||||
|
struct is_float<T> \
|
||||||
|
{ \
|
||||||
|
enum is_float_enum \
|
||||||
|
{ \
|
||||||
|
_YES = 1, \
|
||||||
|
_NO = 0 \
|
||||||
|
}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
GLM_DETAIL_IS_FLOAT(detail::half);
|
||||||
|
GLM_DETAIL_IS_FLOAT(float);
|
||||||
|
GLM_DETAIL_IS_FLOAT(double);
|
||||||
|
GLM_DETAIL_IS_FLOAT(long double);
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// bool
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_bool
|
||||||
|
{
|
||||||
|
enum is_bool_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_bool<bool>
|
||||||
|
{
|
||||||
|
enum is_bool_enum
|
||||||
|
{
|
||||||
|
_YES = 1,
|
||||||
|
_NO = 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// vector
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_vector
|
||||||
|
{
|
||||||
|
enum is_vector_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# define GLM_DETAIL_IS_VECTOR(TYPE) \
|
||||||
|
template <typename T> \
|
||||||
|
struct is_vector<TYPE<T> > \
|
||||||
|
{ \
|
||||||
|
enum is_vector_enum \
|
||||||
|
{ \
|
||||||
|
_YES = 1, \
|
||||||
|
_NO = 0 \
|
||||||
|
}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// matrix
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_matrix
|
||||||
|
{
|
||||||
|
enum is_matrix_enum
|
||||||
|
{
|
||||||
|
_YES = 0,
|
||||||
|
_NO = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GLM_DETAIL_IS_MATRIX(T) \
|
||||||
|
template <> \
|
||||||
|
struct is_matrix \
|
||||||
|
{ \
|
||||||
|
enum is_matrix_enum \
|
||||||
|
{ \
|
||||||
|
_YES = 1, \
|
||||||
|
_NO = 0 \
|
||||||
|
}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// type
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct type
|
||||||
|
{
|
||||||
|
enum type_enum
|
||||||
|
{
|
||||||
|
is_float = is_float<T>::_YES,
|
||||||
|
is_int = is_int<T>::_YES,
|
||||||
|
is_uint = is_uint<T>::_YES,
|
||||||
|
is_bool = is_bool<T>::_YES
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// type
|
||||||
|
|
||||||
|
typedef signed char int8;
|
||||||
|
typedef signed short int16;
|
||||||
|
typedef signed int int32;
|
||||||
|
typedef detail::sint64 int64;
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef detail::uint64 uint64;
|
||||||
|
|
||||||
|
typedef detail::half float16;
|
||||||
|
typedef float float32;
|
||||||
|
typedef double float64;
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// float_or_int_trait
|
||||||
|
|
||||||
|
struct float_or_int_value
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GLM_ERROR,
|
||||||
|
GLM_FLOAT,
|
||||||
|
GLM_INT
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct float_or_int_trait
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_ERROR};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<int8>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<int16>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<int32>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<int64>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<uint8>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<uint16>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<uint32>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<uint64>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_INT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<float16>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_FLOAT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<float32>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_FLOAT};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct float_or_int_trait<float64>
|
||||||
|
{
|
||||||
|
enum{ID = float_or_int_value::GLM_FLOAT};
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace detail
|
||||||
|
}//namespace glm
|
||||||
|
|
||||||
|
#if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2005))
|
||||||
|
# define GLM_DEPRECATED __declspec(deprecated)
|
||||||
|
# define GLM_ALIGN(x) __declspec(align(x))
|
||||||
|
# define GLM_ALIGNED_STRUCT(x) __declspec(align(x)) struct
|
||||||
|
# define GLM_RESTRICT __declspec(restrict)
|
||||||
|
# define GLM_RESTRICT_VAR __restrict
|
||||||
|
# define GLM_CONSTEXPR
|
||||||
|
#elif((GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_LLVM_GCC)) && (GLM_COMPILER >= GLM_COMPILER_GCC31))
|
||||||
|
# define GLM_DEPRECATED __attribute__((__deprecated__))
|
||||||
|
# define GLM_ALIGN(x) __attribute__((aligned(x)))
|
||||||
|
# define GLM_ALIGNED_STRUCT(x) struct __attribute__((aligned(x)))
|
||||||
|
# if(GLM_COMPILER >= GLM_COMPILER_GCC33)
|
||||||
|
# define GLM_RESTRICT __restrict__
|
||||||
|
# define GLM_RESTRICT_VAR __restrict__
|
||||||
|
# else
|
||||||
|
# define GLM_RESTRICT
|
||||||
|
# define GLM_RESTRICT_VAR
|
||||||
|
# endif
|
||||||
|
# define GLM_RESTRICT __restrict__
|
||||||
|
# define GLM_RESTRICT_VAR __restrict__
|
||||||
|
# if((GLM_COMPILER >= GLM_COMPILER_GCC47) && ((GLM_LANG & GLM_LANG_CXX0X) == GLM_LANG_CXX0X))
|
||||||
|
# define GLM_CONSTEXPR constexpr
|
||||||
|
# else
|
||||||
|
# define GLM_CONSTEXPR
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define GLM_DEPRECATED
|
||||||
|
# define GLM_ALIGN
|
||||||
|
# define GLM_ALIGNED_STRUCT(x)
|
||||||
|
# define GLM_RESTRICT
|
||||||
|
# define GLM_RESTRICT_VAR
|
||||||
|
# define GLM_CONSTEXPR
|
||||||
|
#endif//GLM_COMPILER
|
||||||
|
|
||||||
|
#endif//glm_core_detail
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue