merge in a year's worth of CERN work
This commit is contained in:
commit
c1ec14bcac
|
@ -414,6 +414,6 @@ void CALLBACK tessErrorCB( GLenum errorCode )
|
|||
errorStr = gluErrorString( errorCode );
|
||||
|
||||
// DEBUG //
|
||||
D( printf( "Tess ERROR: %s\n", errorStr ); )
|
||||
DBG( printf( "Tess ERROR: %s\n", errorStr ); )
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ int VRML_MODEL_PARSER::readChildren( FILE* file, int* LineNum )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "ReadChildren error line %d <%s> \n", *LineNum, text ) );
|
||||
DBG( printf( "ReadChildren error line %d <%s> \n", *LineNum, text ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ int VRML_MODEL_PARSER::readShape( FILE* file, int* LineNum )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "ReadShape error line %d <%s> \n", *LineNum, text ) );
|
||||
DBG( printf( "ReadShape error line %d <%s> \n", *LineNum, text ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ int VRML_MODEL_PARSER::readAppearance( FILE* file, int* LineNum )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "ReadAppearance error line %d <%s> \n", *LineNum, text ) );
|
||||
DBG( printf( "ReadAppearance error line %d <%s> \n", *LineNum, text ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,19 +197,19 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
|||
if( !parseDoubleTriplet( properties[ wxT( "diffuseColor" ) ],
|
||||
material->m_DiffuseColor ) )
|
||||
{
|
||||
D( printf("diffuseColor parsing error") );
|
||||
DBG( printf("diffuseColor parsing error") );
|
||||
}
|
||||
|
||||
if( !parseDoubleTriplet( properties[ wxT( "specularColor" ) ],
|
||||
material->m_SpecularColor ) )
|
||||
{
|
||||
D( printf("specularColor parsing error") );
|
||||
DBG( printf("specularColor parsing error") );
|
||||
}
|
||||
|
||||
if( !parseDoubleTriplet( properties[ wxT( "emissiveColor" ) ],
|
||||
material->m_EmissiveColor ) )
|
||||
{
|
||||
D( printf("emissiveColor parsing error") );
|
||||
DBG( printf("emissiveColor parsing error") );
|
||||
}
|
||||
|
||||
wxStringTokenizer values;
|
||||
|
@ -221,7 +221,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "ambienterror" ) );
|
||||
DBG( printf( "ambienterror" ) );
|
||||
}
|
||||
|
||||
values.SetString( properties[ wxT( "shininess" ) ] );
|
||||
|
@ -232,7 +232,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "shininess error" ) );
|
||||
DBG( printf( "shininess error" ) );
|
||||
}
|
||||
|
||||
values.SetString( properties[ wxT( "transparency" ) ] );
|
||||
|
@ -243,7 +243,7 @@ void X3D_MODEL_PARSER::readMaterial( wxXmlNode* aMatNode )
|
|||
}
|
||||
else
|
||||
{
|
||||
D( printf( "trans error") );
|
||||
DBG( printf( "trans error") );
|
||||
}
|
||||
|
||||
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( &angle ) ) )
|
||||
{
|
||||
D( printf("rotation read error") );
|
||||
DBG( printf("rotation read error") );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
D( printf( "Number of points is incorrect" ) );
|
||||
DBG( printf( "Number of points is incorrect" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ option( KICAD_SCRIPTING_MODULES
|
|||
option( KICAD_SCRIPTING_WXPYTHON
|
||||
"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:
|
||||
# PYTHON_EXECUTABLE can be defined when invoking cmake
|
||||
# ( use -DPYTHON_EXECUTABLE=<python path>/python.exe or python2 )
|
||||
|
@ -230,12 +230,27 @@ include( ExternalProject )
|
|||
#================================================
|
||||
include( CheckFindPackageResult )
|
||||
|
||||
# Turn on wxWidgets compatibility mode for some classes
|
||||
add_definitions(-DWX_COMPATIBILITY)
|
||||
|
||||
#######################
|
||||
# Find OpenGL library #
|
||||
#######################
|
||||
find_package( OpenGL QUIET )
|
||||
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
|
||||
#################################################
|
||||
include( download_boost )
|
||||
|
@ -360,6 +375,7 @@ add_subdirectory( cvpcb )
|
|||
add_subdirectory( eeschema )
|
||||
add_subdirectory( gerbview )
|
||||
add_subdirectory( kicad )
|
||||
add_subdirectory( lib_dxf )
|
||||
add_subdirectory( pcbnew )
|
||||
add_subdirectory( polygon )
|
||||
add_subdirectory( pagelayout_editor )
|
||||
|
@ -375,12 +391,14 @@ add_subdirectory( tools )
|
|||
add_dependencies( pcbnew boost )
|
||||
add_dependencies( eeschema boost )
|
||||
add_dependencies( cvpcb boost )
|
||||
add_dependencies( gal boost )
|
||||
add_dependencies( common boost )
|
||||
add_dependencies( pcbcommon boost )
|
||||
add_dependencies( 3d-viewer boost )
|
||||
add_dependencies( pcad2kicadpcb boost )
|
||||
add_dependencies( polygon 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(
|
||||
./dialogs
|
||||
./dialog_about
|
||||
${CAIRO_INCLUDE_DIR}
|
||||
${GLEW_INCLUDE_DIR}
|
||||
../3d-viewer
|
||||
../pcbnew
|
||||
../polygon
|
||||
${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
|
||||
dialog_about/AboutDialog_main.cpp
|
||||
dialog_about/dialog_about.cpp
|
||||
|
@ -95,6 +148,32 @@ set(COMMON_SRCS
|
|||
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})
|
||||
|
||||
set(PCB_COMMON_SRCS
|
||||
|
@ -151,6 +230,10 @@ set(PCB_COMMON_SRCS
|
|||
fp_lib_table.cpp
|
||||
)
|
||||
|
||||
set(PCB_COMMON_SRCS
|
||||
${PCB_COMMON_SRCS}
|
||||
../pcbnew/pcb_painter.cpp
|
||||
)
|
||||
|
||||
# add -DPCBNEW to compilation of these PCBNEW sources
|
||||
set_source_files_properties( ${PCB_COMMON_SRCS} PROPERTIES
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
|
||||
#include "../eeschema/dialogs/dialog_schematic_find.h"
|
||||
|
||||
|
||||
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
|
||||
|
||||
|
||||
enum textbox {
|
||||
ID_TEXTBOX_LIST = 8010
|
||||
};
|
||||
|
@ -190,8 +194,28 @@ bool EDA_ITEM::Replace( wxFindReplaceData& aSearchData, wxString& aText )
|
|||
wxCHECK_MSG( IsReplaceable(), false,
|
||||
wxT( "Attempt to replace text in <" ) + GetClass() + wxT( "> item." ) );
|
||||
|
||||
return aText.Replace( aSearchData.GetFindString(),
|
||||
aSearchData.GetReplaceString(), false ) != 0;
|
||||
wxString searchString = (aSearchData.GetFlags() & wxFR_MATCHCASE) ? aText.Upper() : aText;
|
||||
|
||||
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)
|
||||
|
||||
// A function that should have been in wxWidgets
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <macros.h>
|
||||
#include <id.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <class_drawpanel_gal.h>
|
||||
#include <class_base_screen.h>
|
||||
#include <msgpanel.h>
|
||||
#include <wxstruct.h>
|
||||
|
@ -42,10 +43,11 @@
|
|||
#include <kicad_device_context.h>
|
||||
#include <dialog_helpers.h>
|
||||
#include <base_units.h>
|
||||
#include <vector2d.h>
|
||||
#include <math/box2.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
|
||||
|
@ -100,6 +102,8 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( wxWindow* aParent,
|
|||
m_HotkeysZoomAndGridList = NULL;
|
||||
|
||||
m_canvas = NULL;
|
||||
m_galCanvas = NULL;
|
||||
m_galCanvasActive = false;
|
||||
m_messagePanel = NULL;
|
||||
m_currentScreen = NULL;
|
||||
m_toolId = ID_NO_TOOL_SELECTED;
|
||||
|
@ -224,6 +228,12 @@ void EDA_DRAW_FRAME::SkipNextLeftButtonReleaseEvent()
|
|||
void EDA_DRAW_FRAME::OnToggleGridState( wxCommandEvent& aEvent )
|
||||
{
|
||||
SetGridVisibility( !IsGridVisible() );
|
||||
if( m_galCanvasActive )
|
||||
{
|
||||
m_galCanvas->GetGAL()->SetGridVisibility( IsGridVisible() );
|
||||
m_galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
|
||||
}
|
||||
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
|
||||
|
@ -376,7 +386,15 @@ void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event )
|
|||
m_LastGridSizeId = id - ID_POPUP_GRID_LEVEL_1000;
|
||||
screen->SetGrid( id );
|
||||
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;
|
||||
|
||||
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 );
|
||||
|
||||
// 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.
|
||||
double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
|
||||
|
@ -748,11 +780,11 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
if( screen->m_Center )
|
||||
{
|
||||
// half page offset.
|
||||
xIU += pageRectIU.width / 2.0;
|
||||
yIU += pageRectIU.height / 2.0;
|
||||
xIU += pageRectIU.GetWidth() / 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;
|
||||
|
||||
// put "int" limits on the clientRect
|
||||
|
@ -765,13 +797,13 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
if( clientRectIU.GetBottom() > VIRT_MAX )
|
||||
clientRectIU.MoveBottomTo( VIRT_MAX );
|
||||
|
||||
centerPositionIU.x = KiROUND( clientRectIU.x + clientRectIU.width/2 );
|
||||
centerPositionIU.y = KiROUND( clientRectIU.y + clientRectIU.height/2 );
|
||||
centerPositionIU.x = KiROUND( clientRectIU.GetX() + clientRectIU.GetWidth() / 2 );
|
||||
centerPositionIU.y = KiROUND( clientRectIU.GetY() + clientRectIU.GetHeight() / 2 );
|
||||
|
||||
if( screen->m_Center )
|
||||
{
|
||||
centerPositionIU.x -= KiROUND( pageRectIU.width / 2.0 );
|
||||
centerPositionIU.y -= KiROUND( pageRectIU.height / 2.0 );
|
||||
centerPositionIU.x -= KiROUND( pageRectIU.GetWidth() / 2.0 );
|
||||
centerPositionIU.y -= KiROUND( pageRectIU.GetHeight() / 2.0 );
|
||||
}
|
||||
|
||||
DSIZE virtualSizeIU;
|
||||
|
@ -782,26 +814,26 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
}
|
||||
else
|
||||
{
|
||||
double pageCenterX = pageRectIU.x + ( pageRectIU.width / 2 );
|
||||
double clientCenterX = clientRectIU.x + ( clientRectIU.width / 2 );
|
||||
double pageCenterX = pageRectIU.GetX() + ( pageRectIU.GetWidth() / 2 );
|
||||
double clientCenterX = clientRectIU.GetX() + ( clientRectIU.GetWidth() / 2 );
|
||||
|
||||
if( clientRectIU.width > pageRectIU.width )
|
||||
if( clientRectIU.GetWidth() > pageRectIU.GetWidth() )
|
||||
{
|
||||
if( pageCenterX > clientCenterX )
|
||||
virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
|
||||
else if( pageCenterX < clientCenterX )
|
||||
virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
|
||||
else
|
||||
virtualSizeIU.x = clientRectIU.width;
|
||||
virtualSizeIU.x = clientRectIU.GetWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
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 )
|
||||
virtualSizeIU.x = pageRectIU.width + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
|
||||
virtualSizeIU.x = pageRectIU.GetWidth() + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
|
||||
else
|
||||
virtualSizeIU.x = pageRectIU.width;
|
||||
virtualSizeIU.x = pageRectIU.GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,28 +843,28 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
}
|
||||
else
|
||||
{
|
||||
double pageCenterY = pageRectIU.y + ( pageRectIU.height / 2 );
|
||||
double clientCenterY = clientRectIU.y + ( clientRectIU.height / 2 );
|
||||
double pageCenterY = pageRectIU.GetY() + ( pageRectIU.GetHeight() / 2 );
|
||||
double clientCenterY = clientRectIU.GetY() + ( clientRectIU.GetHeight() / 2 );
|
||||
|
||||
if( clientRectIU.height > pageRectIU.height )
|
||||
if( clientRectIU.GetHeight() > pageRectIU.GetHeight() )
|
||||
{
|
||||
if( pageCenterY > clientCenterY )
|
||||
virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
|
||||
else if( pageCenterY < clientCenterY )
|
||||
virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
|
||||
else
|
||||
virtualSizeIU.y = clientRectIU.height;
|
||||
virtualSizeIU.y = clientRectIU.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pageCenterY > clientCenterY )
|
||||
virtualSizeIU.y = pageRectIU.height +
|
||||
virtualSizeIU.y = pageRectIU.GetHeight() +
|
||||
( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
|
||||
else if( pageCenterY < clientCenterY )
|
||||
virtualSizeIU.y = pageRectIU.height +
|
||||
virtualSizeIU.y = pageRectIU.GetHeight() +
|
||||
( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
|
||||
else
|
||||
virtualSizeIU.y = pageRectIU.height;
|
||||
virtualSizeIU.y = pageRectIU.GetHeight();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,8 +879,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
}
|
||||
else
|
||||
{
|
||||
screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.width ) / 2.0 );
|
||||
screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.height ) / 2.0 );
|
||||
screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.GetWidth() ) / 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
|
||||
|
@ -867,8 +899,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
// center position at the center of client rectangle.
|
||||
SetScrollCenterPosition( centerPositionIU );
|
||||
|
||||
double posX = centerPositionIU.x - clientRectIU.width /2.0 - screen->m_DrawOrg.x;
|
||||
double posY = centerPositionIU.y - clientRectIU.height/2.0 - screen->m_DrawOrg.y;
|
||||
double posX = centerPositionIU.x - clientRectIU.GetWidth() / 2.0 - screen->m_DrawOrg.x;
|
||||
double posY = centerPositionIU.y - clientRectIU.GetHeight() / 2.0 - screen->m_DrawOrg.y;
|
||||
|
||||
// Convert scroll bar position to device units.
|
||||
posX = KiROUND( posX * scale );
|
||||
|
@ -919,6 +951,61 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
|
|||
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 >--------------------------------------------
|
||||
|
||||
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 >--------------------------------------------
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <macros.h>
|
||||
#include <id.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <class_drawpanel_gal.h>
|
||||
#include <class_base_screen.h>
|
||||
#include <wxstruct.h>
|
||||
|
||||
|
@ -84,10 +85,17 @@ END_EVENT_TABLE()
|
|||
|
||||
EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id,
|
||||
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 )
|
||||
#endif
|
||||
{
|
||||
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_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()
|
||||
{
|
||||
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 <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.
|
||||
#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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
|
@ -98,6 +115,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
|||
wxArrayString* list = NULL;
|
||||
wxString text = m_Text;
|
||||
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
|
||||
int linecount = 1;
|
||||
|
||||
if( m_MultilineAllowed )
|
||||
{
|
||||
|
@ -109,12 +127,14 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
|||
text = list->Item( aLine );
|
||||
else
|
||||
text = list->Item( 0 );
|
||||
|
||||
linecount = list->GetCount();
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the H and V size
|
||||
int dx = LenSize( text );
|
||||
int dy = GetInterline();
|
||||
int dy = GetInterline( aThickness );
|
||||
|
||||
/* Creates bounding box (rectangle) for an horizontal text */
|
||||
wxSize textsize = wxSize( dx, dy );
|
||||
|
@ -175,7 +195,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
|||
break;
|
||||
|
||||
case GR_TEXT_VJUSTIFY_CENTER:
|
||||
rect.SetY( rect.GetY() - (dy / 2) );
|
||||
rect.SetY( rect.GetY() - ( dy / 2) );
|
||||
break;
|
||||
|
||||
case GR_TEXT_VJUSTIFY_BOTTOM:
|
||||
|
@ -183,6 +203,30 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
|
|||
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.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();
|
||||
|
||||
#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 );
|
||||
|
||||
for( unsigned i = 0; i<list->Count(); i++ )
|
||||
{
|
||||
wxString txt = list->Item( i );
|
||||
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
||||
aDrawMode, aFillMode,
|
||||
i ? UNSPECIFIED_COLOR : aAnchor_color,
|
||||
txt, pos );
|
||||
aDrawMode, aFillMode, txt, pos );
|
||||
pos += offset;
|
||||
}
|
||||
|
||||
|
@ -243,15 +303,21 @@ void EDA_TEXT::Draw( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aOffset,
|
|||
}
|
||||
else
|
||||
drawOneLineOfText( aClipBox, aDC, aOffset, aColor,
|
||||
aDrawMode, aFillMode,
|
||||
aAnchor_color, m_Text, m_Pos );
|
||||
aDrawMode, aFillMode, 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,
|
||||
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
||||
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
||||
EDA_COLOR_T aAnchor_color,
|
||||
wxString& aText, wxPoint aPos )
|
||||
{
|
||||
int width = m_Thickness;
|
||||
|
@ -262,14 +328,6 @@ void EDA_TEXT::drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
|||
if( aDrawMode != UNSPECIFIED_DRAWMODE )
|
||||
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 )
|
||||
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 candidate = BLACK;
|
||||
return ColorFindNearest( aColor.Red(), aColor.Green(), aColor.Blue() );
|
||||
}
|
||||
|
||||
// These are ints because we will subtract them later
|
||||
int r = aColor.Red();
|
||||
int g = aColor.Green();
|
||||
int b = aColor.Blue();
|
||||
EDA_COLOR_T ColorFindNearest( int aR, int aG, int aB )
|
||||
{
|
||||
EDA_COLOR_T candidate = BLACK;
|
||||
|
||||
/* 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
|
||||
|
@ -1511,11 +1511,11 @@ EDA_COLOR_T ColorFindNearest( const wxColour &aColor )
|
|||
for( EDA_COLOR_T trying = BLACK; trying < NBCOLORS; trying = NextColor(trying) )
|
||||
{
|
||||
const StructColors &c = g_ColorRefs[trying];
|
||||
int distance = (r - c.m_Red) * (r - c.m_Red) +
|
||||
(g - c.m_Green) * (g - c.m_Green) +
|
||||
(b - c.m_Blue) * (b - c.m_Blue);
|
||||
if( distance < nearest_distance && c.m_Red >= r &&
|
||||
c.m_Green >= g && c.m_Blue >= b )
|
||||
int distance = (aR - c.m_Red) * (aR - c.m_Red) +
|
||||
(aG - c.m_Green) * (aG - c.m_Green) +
|
||||
(aB - c.m_Blue) * (aB - c.m_Blue);
|
||||
if( distance < nearest_distance && c.m_Red >= aR &&
|
||||
c.m_Green >= aG && c.m_Blue >= aB )
|
||||
{
|
||||
nearest_distance = distance;
|
||||
candidate = trying;
|
||||
|
|
|
@ -65,7 +65,7 @@ void GRID_TRICKS::getSelectedArea()
|
|||
wxArrayInt cols = m_grid->GetSelectedCols();
|
||||
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() )
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ void GRID_TRICKS::getSelectedArea()
|
|||
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>
|
||||
|
||||
|
||||
const wxString traceFindReplace( wxT( "KicadFindReplace" ) );
|
||||
|
||||
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
|
||||
// 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 <id.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 <wxstruct.h>
|
||||
#include <kicad_device_context.h>
|
||||
|
@ -41,7 +44,6 @@
|
|||
#include <base_units.h>
|
||||
|
||||
|
||||
|
||||
void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer )
|
||||
{
|
||||
AdjustScrollBars( aCenterPoint );
|
||||
|
@ -82,7 +84,8 @@ void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
|
|||
if( screen->m_FirstRedraw )
|
||||
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 );
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -101,11 +101,27 @@ target_link_libraries( cvpcb
|
|||
common
|
||||
bitmaps
|
||||
polygon
|
||||
gal
|
||||
${wxWidgets_LIBRARIES}
|
||||
${OPENGL_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 )
|
||||
target_link_libraries( cvpcb github_plugin )
|
||||
endif()
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <appl_wxstruct.h>
|
||||
#include <common.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <class_drawpanel_gal.h>
|
||||
#include <confirm.h>
|
||||
#include <macros.h>
|
||||
#include <bitmaps.h>
|
||||
|
@ -121,7 +122,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* parent,
|
|||
EDA_PANEINFO mesg;
|
||||
mesg.MessageToolbarPane();
|
||||
|
||||
|
||||
m_galCanvas->Hide();
|
||||
|
||||
m_auimgr.AddPane( m_mainToolBar,
|
||||
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() );
|
||||
|
||||
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?" ) ) )
|
||||
{
|
||||
try
|
||||
|
@ -292,7 +292,7 @@ int CVPCB_MAINFRAME::SaveCmpLinkFile( const wxString& aFullFileName )
|
|||
{
|
||||
DisplayError( this,
|
||||
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( 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 )
|
||||
{
|
||||
D( printf( "OnListItemDeselected()\n" ); )
|
||||
DBG( printf( "OnListItemDeselected()\n" ); )
|
||||
|
||||
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 )
|
||||
{
|
||||
D( printf( "OnListItemSelected()\n" ); )
|
||||
DBG( printf( "OnListItemSelected()\n" ); )
|
||||
|
||||
// remember the selected row, statically
|
||||
s_SelectedRow = event.GetIndex();
|
||||
|
@ -460,7 +460,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::moveUpButtonHandler( wxCommandEvent& ev
|
|||
// and in the fieldListCtrl
|
||||
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 ) ) ); )
|
||||
|
||||
m_FieldsBuf[fieldNdx - 1] = m_FieldsBuf[fieldNdx];
|
||||
|
@ -880,12 +880,12 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
|
|||
if( mirror == CMP_MIRROR_X )
|
||||
{
|
||||
mirrorRadioBox->SetSelection( 1 );
|
||||
D( printf( "mirror=X,1\n" ); )
|
||||
DBG( printf( "mirror=X,1\n" ); )
|
||||
}
|
||||
else if( mirror == CMP_MIRROR_Y )
|
||||
{
|
||||
mirrorRadioBox->SetSelection( 2 );
|
||||
D( printf( "mirror=Y,2\n" ); )
|
||||
DBG( printf( "mirror=Y,2\n" ); )
|
||||
}
|
||||
else
|
||||
mirrorRadioBox->SetSelection( 0 );
|
||||
|
@ -905,7 +905,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyOptionsToPanel()
|
|||
// Show the "Parts Locked" option?
|
||||
if( !m_LibEntry || !m_LibEntry->UnitsLocked() )
|
||||
{
|
||||
D( printf( "partsAreLocked->false\n" ); )
|
||||
DBG( printf( "partsAreLocked->false\n" ); )
|
||||
partsAreLockedLabel->Show( false );
|
||||
}
|
||||
|
||||
|
|
|
@ -480,7 +480,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
|||
// fixed fields:
|
||||
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] );
|
||||
}
|
||||
|
||||
|
@ -505,7 +505,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
|||
// values from the component will be set.
|
||||
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.SetText( it->m_Value ); // empty? ok too.
|
||||
|
@ -517,7 +517,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
|||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
|
|||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
@ -731,11 +731,11 @@ bool DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copyPanelToSelectedField()
|
|||
if( field.GetId() >= MANDATORY_FIELDS )
|
||||
{
|
||||
wxString name = fieldNameTextCtrl->GetValue();
|
||||
D( printf("name:%s\n", TO_UTF8( name ) ); )
|
||||
DBG( printf("name:%s\n", TO_UTF8( 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
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
*/
|
||||
enum SchematicFindReplaceFlags
|
||||
{
|
||||
// The last wxFindReplaceFlag enum is wxFR_MATCHCASE.
|
||||
// The last wxFindReplaceFlag enum is wxFR_MATCHCASE = 0x4.
|
||||
|
||||
/// Search the current sheet only.
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -680,7 +680,7 @@ void SCH_EDIT_FRAME::LoadSettings()
|
|||
catch( IO_ERROR& e )
|
||||
{
|
||||
// @todo show error msg
|
||||
D( printf( "templatefieldnames parsing error: '%s'\n",
|
||||
DBG( printf( "templatefieldnames parsing error: '%s'\n",
|
||||
TO_UTF8( e.errorText ) ); )
|
||||
}
|
||||
}
|
||||
|
@ -751,7 +751,7 @@ void SCH_EDIT_FRAME::SaveSettings()
|
|||
|
||||
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() );
|
||||
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 )
|
||||
{
|
||||
static wxPoint itemPosition; // the actual position of the matched item.
|
||||
static wxPoint itemPosition; // the actual position of the matched item.
|
||||
|
||||
SCH_SHEET_LIST schematic;
|
||||
wxString msg;
|
||||
SCH_FIND_REPLACE_DATA searchCriteria;
|
||||
bool warpCursor = !( aEvent.GetFlags() & FR_NO_WARP_CURSOR );
|
||||
SCH_SHEET_LIST schematic;
|
||||
wxString msg;
|
||||
SCH_FIND_REPLACE_DATA searchCriteria;
|
||||
SCH_FIND_COLLECTOR_DATA data;
|
||||
|
||||
searchCriteria.SetFlags( aEvent.GetFlags() );
|
||||
|
@ -326,6 +325,88 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
|||
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 )
|
||||
{
|
||||
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 " ) +
|
||||
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
|
||||
// has no effect on objects that don't support hiding. If this is a close find
|
||||
// dialog event, clear the temporary visibility flag.
|
||||
if( aEvent.GetEventType() == wxEVT_COMMAND_FIND_CLOSE )
|
||||
m_foundItems.GetItem( data )->SetForceVisible( false );
|
||||
else
|
||||
m_foundItems.GetItem( data )->SetForceVisible( true );
|
||||
item->SetForceVisible( false );
|
||||
else if( item->Type() == SCH_FIELD_T && !( (SCH_FIELD*) item )->IsVisible() )
|
||||
item->SetForceVisible( true );
|
||||
|
||||
if( sheet->PathHumanReadable() != m_CurrentSheet->PathHumanReadable() )
|
||||
{
|
||||
|
@ -371,61 +454,3 @@ void SCH_EDIT_FRAME::OnFindSchematicItem( wxFindDialogEvent& aEvent )
|
|||
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -424,7 +424,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
|
|||
wxFileName tmpFile = aFullFileName;
|
||||
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() );
|
||||
if( !ret )
|
||||
|
@ -442,7 +442,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
|
|||
tmpFile.GetFullPath(),
|
||||
aFullFileName );
|
||||
|
||||
D(printf("commandLine:'%s'\n", TO_UTF8( commandLine ) );)
|
||||
DBG(printf("commandLine:'%s'\n", TO_UTF8( commandLine ) );)
|
||||
|
||||
ProcessExecute( commandLine, wxEXEC_SYNC );
|
||||
}
|
||||
|
|
|
@ -347,7 +347,7 @@ bool SCH_FIND_COLLECTOR::PassedEnd() const
|
|||
if( GetCount() == 0 )
|
||||
return true;
|
||||
|
||||
if( !(flags & FR_SEARCH_WRAP) )
|
||||
if( !(flags & FR_SEARCH_WRAP) || (flags & FR_SEARCH_REPLACE) )
|
||||
{
|
||||
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() )
|
||||
return false;
|
||||
|
@ -464,15 +464,10 @@ bool SCH_FIND_COLLECTOR::ReplaceItem()
|
|||
|
||||
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 )
|
||||
{
|
||||
Remove( m_foundIndex );
|
||||
m_data.erase( m_data.begin() + m_foundIndex );
|
||||
}
|
||||
m_forceSearch = true;
|
||||
|
||||
return replaced;
|
||||
}
|
||||
|
|
|
@ -237,15 +237,6 @@ class SCH_FIND_COLLECTOR : public COLLECTOR
|
|||
/// performed even if the search criteria hasn't changed.
|
||||
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
|
||||
* is a helper to dump the items in the find list for debugging purposes.
|
||||
|
@ -266,8 +257,24 @@ public:
|
|||
m_forceSearch = false;
|
||||
}
|
||||
|
||||
void Empty()
|
||||
{
|
||||
m_foundIndex = 0;
|
||||
COLLECTOR::Empty();
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
bool ReplaceItem();
|
||||
bool ReplaceItem( SCH_SHEET_PATH* aSheetPath = NULL );
|
||||
|
||||
SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL );
|
||||
|
||||
|
@ -340,6 +347,8 @@ public:
|
|||
* value searches the entire schematic hierarchy.
|
||||
*/
|
||||
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;
|
||||
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,
|
||||
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 );
|
||||
|
||||
if( component->GetPartCount() > 1 )
|
||||
text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() );
|
||||
// if( component->GetPartCount() > 1 )
|
||||
// text << LIB_COMPONENT::ReturnSubReference( component->GetUnit() );
|
||||
|
||||
isReplaced = EDA_ITEM::Replace( aSearchData, text );
|
||||
|
||||
|
|
|
@ -438,6 +438,7 @@ SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet )
|
|||
m_index = 0;
|
||||
m_count = 0;
|
||||
m_List = NULL;
|
||||
m_isRootSheet = false;
|
||||
|
||||
if( aSheet == NULL )
|
||||
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 )
|
||||
{
|
||||
if( aSheet == g_RootSheet )
|
||||
m_isRootSheet = true;
|
||||
|
||||
if( m_List == NULL )
|
||||
{
|
||||
int count = aSheet->CountSheets();
|
||||
|
@ -702,3 +706,25 @@ bool SCH_SHEET_LIST::SetComponentFootprint( const wxString& aReference,
|
|||
|
||||
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
|
||||
* internal calculations in BuildSheetList()
|
||||
*/
|
||||
bool m_isRootSheet;
|
||||
SCH_SHEET_PATH m_currList;
|
||||
|
||||
public:
|
||||
|
@ -442,6 +443,15 @@ public:
|
|||
bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
|
||||
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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ int TEMPLATES::AddTemplateFieldName( const TEMPLATE_FIELDNAME& aFieldName )
|
|||
{
|
||||
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 ); )
|
||||
|
||||
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
|
||||
// it and return its index within the container.
|
||||
|
|
|
@ -409,7 +409,7 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
|
|||
|
||||
case AMP_UNKNOWN:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
if( m_GerbMetric )
|
||||
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 )
|
||||
{
|
||||
|
@ -521,7 +521,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
m_ImageNegative = true;
|
||||
else
|
||||
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" ); )
|
||||
break;
|
||||
|
||||
|
@ -531,7 +531,7 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
|
||||
else
|
||||
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" ); )
|
||||
break;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <colors.h>
|
||||
#include <bitmaps.h>
|
||||
#include <richio.h>
|
||||
#include <view/view_item.h>
|
||||
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
||||
|
@ -46,102 +47,8 @@ extern std::ostream& operator <<( std::ostream& out, const wxPoint& pt );
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Enum KICAD_T
|
||||
* 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
|
||||
};
|
||||
/// Flag to enable find and replace tracing using the WXTRACE environment variable.
|
||||
extern const wxString traceFindReplace;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -400,6 +307,9 @@ public:
|
|||
#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
|
||||
///< 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
|
||||
|
||||
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
|
||||
* schematics and boards.
|
||||
*/
|
||||
class EDA_ITEM
|
||||
class EDA_ITEM : public KIGFX::VIEW_ITEM
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -450,12 +360,7 @@ public:
|
|||
EDA_ITEM( const EDA_ITEM& base );
|
||||
virtual ~EDA_ITEM() { };
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/// @copydoc VIEW_ITEM::Type()
|
||||
KICAD_T Type() const { return m_StructType; }
|
||||
|
||||
void SetTimeStamp( time_t aNewTimeStamp ) { m_TimeStamp = aNewTimeStamp; }
|
||||
|
@ -479,6 +384,16 @@ public:
|
|||
inline bool IsDragging() const { return m_Flags & IS_DRAGGED; }
|
||||
inline bool IsSelected() const { return m_Flags & SELECTED; }
|
||||
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();
|
||||
|
||||
|
@ -748,6 +663,12 @@ public:
|
|||
*/
|
||||
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)
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,6 +90,10 @@ public:
|
|||
|
||||
// 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.
|
||||
*/
|
||||
|
@ -269,6 +273,9 @@ public:
|
|||
static std::string FormatInternalUnits( const wxPoint& aPoint );
|
||||
|
||||
static std::string FormatInternalUnits( const wxSize& aSize );
|
||||
|
||||
/// @copydoc VIEW_ITEM::ViewGetLayers()
|
||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const;
|
||||
};
|
||||
|
||||
#endif /* BOARD_ITEM_STRUCT_H */
|
||||
|
|
|
@ -317,6 +317,9 @@ public:
|
|||
*/
|
||||
void RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground = true );
|
||||
|
||||
/// @copydoc wxWindow::Refresh()
|
||||
virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL );
|
||||
|
||||
/**
|
||||
* Function GetScreenCenterLogicalPosition
|
||||
* @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
|
||||
#define CLASS_WORKSHEET_DATA_ITEM_H
|
||||
|
||||
#include <vector2d.h>
|
||||
#include <math/vector2d.h>
|
||||
#include <eda_text.h>
|
||||
#include <class_bitmap_base.h>
|
||||
|
||||
|
|
|
@ -139,6 +139,14 @@ EDA_COLOR_T ColorByName( const wxChar *aName );
|
|||
/// Find the nearest color match
|
||||
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
|
||||
* white on it
|
||||
|
|
|
@ -236,6 +236,8 @@ public:
|
|||
* for single line text, aLine is unused
|
||||
* If aLine == -1, the full area (considering all lines) is returned
|
||||
* @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.
|
||||
*/
|
||||
EDA_RECT GetTextBox( int aLine = -1, int aThickness = -1, bool aInvertY = false ) const;
|
||||
|
@ -244,11 +246,11 @@ public:
|
|||
* Function GetInterline
|
||||
* return the distance between 2 text lines
|
||||
* 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
|
||||
{
|
||||
return (( m_Size.y * 14 ) / 10) + m_Thickness;
|
||||
}
|
||||
int GetInterline( int aTextThickness = -1 ) const;
|
||||
|
||||
/**
|
||||
* Function GetTextStyleName
|
||||
|
@ -286,15 +288,13 @@ private:
|
|||
* @param aColor = text color
|
||||
* @param aDrawMode = GR_OR, GR_XOR.., -1 to use the current mode.
|
||||
* @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 aPos = the position of this line ).
|
||||
*/
|
||||
void drawOneLineOfText( EDA_RECT* aClipBox, wxDC* aDC,
|
||||
const wxPoint& aOffset, EDA_COLOR_T aColor,
|
||||
GR_DRAWMODE aDrawMode, EDA_DRAW_MODE_T aFillMode,
|
||||
EDA_COLOR_T aAnchor_color, wxString& aText,
|
||||
wxPoint aPos );
|
||||
wxString& aText, wxPoint aPos );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#define WIN_STRING_DIR_SEP wxT( "\\" )
|
||||
|
||||
#ifdef DEBUG
|
||||
#define D(x) x
|
||||
#define DBG(x) x
|
||||
#else
|
||||
#define D(x) // nothing
|
||||
#define DBG(x) // nothing
|
||||
#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