From 3655df08ea25f35d9a9dacabfccdeada4b6ea310 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 5 Jun 2013 14:03:16 +0200 Subject: [PATCH] All: use a S expression to describe the page layout (title block and grid references). Work in progress. This should allow users to define their own page layout. --- .bzrignore | 2 + Documentation/compiling/COMPILING.txt | 18 +- Documentation/compiling/build-config.txt | 14 + Documentation/compiling/build-msw.txt | 22 +- Documentation/compiling/mac-osx.txt | 7 +- Documentation/releases/2010-mar-14.html | 530 ------------------- Documentation/releases/2010-mar-14.txt | 40 -- common/CMakeLists.txt | 12 + common/hotkeys_basic.cpp | 1 + common/page_layout_default_description.cpp | 72 +++ common/page_layout_reader.cpp | 461 +++++++++++++++++ common/page_layout_reader.keywords | 35 ++ common/title_block_shapes.cpp | 570 ++++++++------------- common/title_block_shapes_gost.cpp | 13 +- common/worksheet.cpp | 68 ++- include/class_title_block.h | 121 +++-- include/vector2d.h | 2 +- include/worksheet.h | 15 +- include/worksheet_shape_builder.h | 203 +++++++- pcbnew/kicad_plugin.cpp | 40 +- 20 files changed, 1174 insertions(+), 1072 deletions(-) delete mode 100644 Documentation/releases/2010-mar-14.html delete mode 100644 Documentation/releases/2010-mar-14.txt create mode 100644 common/page_layout_default_description.cpp create mode 100644 common/page_layout_reader.cpp create mode 100644 common/page_layout_reader.keywords diff --git a/.bzrignore b/.bzrignore index da05a16fca..3e97e8ac23 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3,9 +3,11 @@ downloads-by-cmake common/netlist_keywords.* common/netlist_lexer.h common/pcb_plot_params_lexer.h +common/page_layout_reader_keywords.cpp common/fp_lib_table_keywords.* include/fp_lib_table_lexer.h include/netlist_lexer.h +include/page_layout_reader_lexer.h eeschema/cmp_library_lexer.h eeschema/cmp_library_keywords.* eeschema/template_fieldnames_keywords.* diff --git a/Documentation/compiling/COMPILING.txt b/Documentation/compiling/COMPILING.txt index 9a4a9dd6d7..3b8501a24f 100644 --- a/Documentation/compiling/COMPILING.txt +++ b/Documentation/compiling/COMPILING.txt @@ -28,16 +28,22 @@ development libaries. After a fresh install you need the following packages to compile and run KiCad from source. -CMake - Cross-platform make -GLUT - The OpenGL Utility Library -wxGTK or wxWidgets - The wxWidgets GUI toolkit with GTK+ bindings +* bzr - Bazaar version control system +* CMake - Cross-platform make +* GLUT - The OpenGL Utility Library +* wxGTK or wxWidgets - The wxWidgets GUI toolkit with GTK+ bindings -Boost - Collection of portable C++ source libraries -Because boost is in the repository of kicad you don't need to install them. +* Boost - Collection of portable C++ source libraries +boost will be automagically downloaded and copied in kicad sources tree, +the first time you compile kicad. Useful, but not required: -Doxygen - Documentation system for several programming languages +* Doxygen - Documentation system for several programming languages +KiCad uses the Bazaar version control system to track source code changes, +and download the boost libraries needed by Kicad. +Be sure you bzr install also includes bzrtools. +boost libraries will be downloaded the first time you build Kicad. Compiler and basic development tools ------------- diff --git a/Documentation/compiling/build-config.txt b/Documentation/compiling/build-config.txt index 228f5cdb18..058106fcb6 100644 --- a/Documentation/compiling/build-config.txt +++ b/Documentation/compiling/build-config.txt @@ -1,3 +1,17 @@ +Bazaar +------ +KiCad uses the Bazaar version control system to track source code changes, +and download the boost libraries needed by Kicad. +The easiest way to get a copy of the KiCad source is to use Bazaar. +Bazaar can be download from http://wiki.bazaar.canonical.com. +Your best bet is to use the stand alone version of Bazaar +(which includes bzrtools, needed by Kicad) rather than one of +the Python specific versions. +Be sure bzrtools is also installed. +boost libraries will be downloaded the first time you build Kicad. + +CMake +----- KiCad uses CMake to generate the build files specific for the target platform specified by the developer. This document attempts to define some of the more common CMake and KiCad build configuration settings. You can use CMake either diff --git a/Documentation/compiling/build-msw.txt b/Documentation/compiling/build-msw.txt index 12726d569c..e5e37ff1b7 100644 --- a/Documentation/compiling/build-msw.txt +++ b/Documentation/compiling/build-msw.txt @@ -26,10 +26,12 @@ languages. Only C is installed by default and C++ is required to build KiCad. Bazaar ------ -KiCad uses the Bazaar version control system to track source code changes. +KiCad uses the Bazaar version control system to track source code changes, +and download the boost libraries needed by Kicad. The easiest way to get a copy of the KiCad source is to use Bazaar. Bazaar -can be download from http://http://wiki.bazaar.canonical.com/WindowsDownloads. -Your best bet is to use the stand alone version of Bazaar rather than one of +can be download from http://wiki.bazaar.canonical.com/WindowsDownloads. +Your best bet is to use the stand alone version of Bazaar +(which includes bzrtools, needed Kicad) rather than one of the Python specific versions. CMake @@ -87,7 +89,7 @@ MinGW linker. Build and Install the wxWidgets Library --------------------------------------- The wxWidgets library is the base that KiCad is built upon. Version 2.9.4 -or later of wxWidgets should be used on Windows. You may be able to build +or later of wxWidgets *should be* used on Windows. You may be able to build KiCad with older versions of wxWidgets but it is not recommended. wxWidgets can be downloaded from http://http://www.wxwidgets.org/downloads/ @@ -107,16 +109,10 @@ install the wxWidgets library into MinGW then enter the following commands: If you want to install wxWidgets in MinGW then enter the following commands: #mkdir Release #cd Release -#../configure --prefix=/mingw --with-opengl +#../configure --prefix=/mingw --enable-monolithic=no --disable-shared --with-opengl #make && make install -#move /mingw/lib/wxmsw*.dll /mingw/bin -The last command is critical so that the libraries are in the MinGW PATH -and can be found at run time. If you want to build a full debugging version -of wxWidgets, add --enable-debug to the configure command. If you are going -to use the GNU debugger, you may also want to build the debugging libraries -with the extra GDB debugging information by adding --enable-debug_gdb to the -configure command. +wxWidgets will be statically linked to Kicad, which avoid issus with wxWidgets dlls Download the KiCad Source Code ------------------------------ @@ -229,5 +225,5 @@ To build the HTML developer documentation, run the following commands: #cd /build/debug #make doxygen-docs -The documentation will be created in the /Documenation/html +The documentation will be created in the /Documentation/html directory. diff --git a/Documentation/compiling/mac-osx.txt b/Documentation/compiling/mac-osx.txt index 1663cf2b6f..c94d1e6666 100644 --- a/Documentation/compiling/mac-osx.txt +++ b/Documentation/compiling/mac-osx.txt @@ -9,6 +9,7 @@ Snow Leopard Requirements * XCode Tools (http://developer.apple.com/tools/xcode) + * bzr (bazaar) * CMake (http://www.cmake.org) * wxWidgets 2.9 (http://www.wxwidgets.org/downloads) * Doxygen (http://www.doxygen.nl) @@ -19,7 +20,7 @@ Building wxWidgets 2.9 Universal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To check if your tools and libraries are installed check with file for architectures. -user@macosx$ file /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.dylib +user@macosx$ file /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.dylib /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.dylib: Mach-O universal binary with 4 architectures /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.dylib (for architecture ppc7400): Mach-O dynamically linked shared library stub ppc @@ -37,7 +38,7 @@ At time of writing (2009-01-16) this is on line 18381 into this: OSX_UNIV_OPTS="-arch ppc -arch i386 -arch x86_64" Building a universal monolib wxWidgets 2.9 with the following parameters: -./configure --enable-unicode=yes --enable-shared=no --enable-monolithic --with-opengl --with-expat=builtin --enable-universal_binary --enable-aui --enable-debug --with-osx_cocoa --with-macosx-sdk=/Developer/SDKs/MacOSX10.5.sdk/ --prefix=/opt/wxwidgets/ +./configure --enable-unicode=yes --enable-shared=no --enable-monolithic --with-opengl --with-expat=builtin --enable-universal_binary --enable-aui --enable-debug --with-osx_cocoa --with-macosx-sdk=/Developer/SDKs/MacOSX10.5.sdk/ --prefix=/opt/wxwidgets/ Should be subsituded with the revision from SVN @@ -91,7 +92,7 @@ It depends on which CMake version you use: //This fixes also BOOST macro errors CMAKE_CXX_FLAGS:STRING=-D__ASSERTMACROS__ -//Build architectures for OSX +//Build architectures for OSX CMAKE_OSX_ARCHITECTURES:STRING=x86_64 -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.5.sdk/ -mmacosx-version-min=10.5 //The product will be built against the headers and libraries located diff --git a/Documentation/releases/2010-mar-14.html b/Documentation/releases/2010-mar-14.html deleted file mode 100644 index 1e3b810b32..0000000000 --- a/Documentation/releases/2010-mar-14.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - - -KiCad 2010-xx-xx Release - - - - -

Common

-
-
    -
  • -

    -Actions can now be undo and redo -

    -
  • -
  • -

    -Menus and tooltips more clear -

    -
  • -
  • -

    -File history now in Open Recent submenu -

    -
  • -
  • -

    -Many new hotkeys added -

    -
  • -
  • -

    -Plot and print dialog rewritten -

    -
  • -
  • -

    -Remember last dialog position and tab -

    -
  • -
  • -

    -Better font shapes -

    -
  • -
  • -

    -Generation of bill of materials -

    -
  • -
  • -

    -Plot SVG output -

    -
  • -
-
-

KiCad

-
-
    -
  • -

    -Issue fixed when opening a project in a directory with a lot of subdirectories -

    -
  • -
  • -

    -If project is noname.pro no error will be displayed -

    -
  • -
-
-

EESchema

-
-
    -
  • -

    -New pin properties dialog -

    -
  • -
-
-

PCBNew

-
-
    -
  • -

    -Advanced layer setup -

    -
  • -
  • -

    -New panel for layer management -

    -
  • -
  • -

    -Support for net classes -

    -
  • -
  • -

    -Incorrect DRC error fixed, DRC min via and min track check -

    -
  • -
  • -

    -Handle local mask clearance and local net clearance -

    -
  • -
  • -

    -Handle zones in connectivity calculations -

    -
  • -
-
-

Core

-
-
    -
  • -

    -Many many bugfixes and cleanups -

    -
  • -
  • -

    -All comments translated to English -

    -
  • -
  • -

    -Moved to wxAUI and dialogs created with wxFormBuilder -

    -
  • -
  • -

    -Full support for Mac OS X with wxWidgets 2.9 -

    -
  • -
-
- - - diff --git a/Documentation/releases/2010-mar-14.txt b/Documentation/releases/2010-mar-14.txt deleted file mode 100644 index f3763b50ba..0000000000 --- a/Documentation/releases/2010-mar-14.txt +++ /dev/null @@ -1,40 +0,0 @@ -KiCad 2010-xx-xx Release -======================== - -== Common - * Actions can now be undo and redo - * Menus and tooltips more clear - * File history now in Open Recent submenu - * Many new hotkeys added - * Plot and print dialog rewritten - * Remember last dialog position and tab - * Better font shapes - * Generation of bill of materials - * Plot SVG output - -== KiCad - * Issue fixed when opening a project in a directory with a lot of subdirectories. - * If project is noname.pro no `error` will be displayed - -== EESchema - * New pin properties dialog - -== PCBNew - * Plot DXF output - * Advanced layer setup - * New panel for layer management - * Support for net classes - * Incorrect DRC error fixed, DRC min via and min track check - * Handle local mask clearance and local net clearance - * Handle zones in connectivity calculations - -== Core - * Many many bugfixes and cleanups - * All comments translated to English - * Moved to wxAUI and dialogs created with wxFormBuilder - * Full support for Mac OS X with wxWidgets 2.9 - -/////////////////////////////////////// -This is a asciidoc formatted file, it can be converted -to PDF,(XHTML) and others. See asciidoc homepage. -/////////////////////////////////////// diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 1e5a24dcdf..f834c2a66f 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -76,6 +76,9 @@ set(COMMON_SRCS msgpanel.cpp netlist_keywords.cpp newstroke_font.cpp + page_layout_default_description.cpp + page_layout_reader_keywords.cpp + page_layout_reader.cpp projet_config.cpp ptree.cpp reporter.cpp @@ -191,6 +194,15 @@ make_lexer( FP_LIB_TABLE_T ) +# auto-generate page layout reader s-expression page_layout_reader_lexer.h +# and title_block_reader_keywords.cpp. +make_lexer( + ${CMAKE_CURRENT_SOURCE_DIR}/page_layout_reader.keywords + ${PROJECT_SOURCE_DIR}/include/page_layout_reader_lexer.h + ${CMAKE_CURRENT_SOURCE_DIR}/page_layout_reader_keywords.cpp + TB_READER_T + ) + # The dsntest may not build properly using MS Visual Studio. if(NOT MSVC) # This one gets made only when testing. diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp index dc5c9ffba8..025168e920 100644 --- a/common/hotkeys_basic.cpp +++ b/common/hotkeys_basic.cpp @@ -519,6 +519,7 @@ int EDA_BASE_FRAME::WriteHotkeyConfig( struct EDA_HOTKEY_CONFIG* aDescList, if( file ) { fputs( TO_UTF8( msg ), file ); + fclose( file ); } else { diff --git a/common/page_layout_default_description.cpp b/common/page_layout_default_description.cpp new file mode 100644 index 0000000000..04e94a84f9 --- /dev/null +++ b/common/page_layout_default_description.cpp @@ -0,0 +1,72 @@ +/** + * @file page_layout_default_description.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 Jean-Pierre Charras . + * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors. + * + * + * 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 + +// height of the band reference grid 2.0 mm +// worksheet frame reference text size 1.3 mm +// default text size 1.5 mm +// default line width 0.15 mm +// frame ref pitch 50 mm + +extern const wxString defaultPageLayout; + +// Default page layout (sizes are in mm) +const wxString defaultPageLayout( wxT( "( page_layout\n" +"(setup (textsize 1.5 1.5) (linewidth 0.15) (textlinewidth 0.15) )" +"(rect (comment rect around the title block) (linewidth 0.15) (start 110 34) (end 2 2) )\n" +"(rect (start 0 0 ltcorner) (end 0 0 rbcorner) (repeat 2) (incrx 2) (incry 2) )\n" +"(line (start 50 2 ltcorner) (end 50 0 ltcorner) (repeat 30) (incrx 50) )\n" +"(tbtext \"1\" (pos 25 1 ltcorner) (font (size 1.3 1.3))(repeat 100) (incrx 50) )\n" +"(line (start 50 2 lbcorner) (end 50 0 lbcorner) (repeat 30) (incrx 50) )\n" +"(tbtext \"1\" (pos 25 1 lbcorner) (font (size 1.3 1.3)) (repeat 100) (incrx 50) )\n" +"(line (start 0 50 ltcorner) (end 2 50 ltcorner) (repeat 30) (incry 50) )\n" +"(tbtext \"A\" (pos 1 25 ltcorner) (font (size 1.3 1.3)) (justify center)(repeat 100) (incry 50) )\n" +"(line (start 0 50 rtcorner) (end 2 50 rtcorner) (repeat 30) (incry 50) )\n" +"(tbtext \"A\" (pos 1 25 rtcorner) (font (size 1.3 1.3)) (justify center) (repeat 100) (incry 50) )\n" +"(tbtext \"Date: %D\" (pos 87 6.9) )\n" +"(line (start 110 5.5) end 2 5.5) )\n" +"(tbtext \"%K\" (pos 108 4.1) (comment Kicad version ) )\n" +"(line (start 110 8.5) end 2 8.5) )\n" +"(tbtext \"Rev: %R\" (pos 24 6.9)(font bold italic)(justify left) )\n" +"(tbtext \"Size: %Z\" (comment Paper format name)(pos 105 6.9) )\n" +"(tbtext \"Id: %S/%N\" (comment Sheet id)(pos 24 4.1) )\n" +"(line (start 110 12.5) end 2 12.5) )\n" +"(tbtext \"Title: %T\" (pos 108 10.7)(font bold (size 2 2)) )\n" +"(tbtext \"File: %F\" (pos 108 14.3) )\n" +"(line (start 110 18.5) end 2 18.5) )\n" +"(tbtext \"Sheet: %P\" (pos 108 17) )\n" +"(tbtext \"%Y\" (comment Company name) (pos 108 20)(font bold) )\n" +"(tbtext \"%C0\" (comment Comment 0) (pos 108 23) )\n" +"(tbtext \"%C1\" (comment Comment 0) (pos 108 26) )\n" +"(tbtext \"%C2\" (comment Comment 0) (pos 108 29) )\n" +"(tbtext \"%C3\" (comment Comment 0) (pos 108 32) )\n" +"(line (start 90 8.5) end 90 5.5) )\n" +"(line (start 26 8.5) end 26 2) )\n" +")\n") ); diff --git a/common/page_layout_reader.cpp b/common/page_layout_reader.cpp new file mode 100644 index 0000000000..140d9e8df1 --- /dev/null +++ b/common/page_layout_reader.cpp @@ -0,0 +1,461 @@ +/** + * @file page_layout_reader.cpp + * @brief read an S expression of description of graphic items and texts + * to build a title block and page layout + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 Jean-Pierre Charras . + * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors. + * + * + * 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 +#include +#include +#include +#include +#include + +// defaultPageLayout is the default page layout description +// using the S expr. +// see page_layout_default_shape.cpp +extern const wxString defaultPageLayout; + +using namespace TB_READER_T; + +/** + * Class PAGE_LAYOUT_READER_PARSER + * holds data and functions pertinent to parsing a S-expression file + * for a WORKSHEET_LAYOUT. + */ +class PAGE_LAYOUT_READER_PARSER : public PAGE_LAYOUT_READER_LEXER +{ + DSIZE m_defaultTextSize; // Default text size, when not defined inside a tbtext + double m_defaultLineWidth; + double m_defaulTextLineWidth; + +public: + PAGE_LAYOUT_READER_PARSER( const char* aLine, const wxString& aSource ); + void Parse( WORKSHEET_LAYOUT* aLayout ) + throw( PARSE_ERROR, IO_ERROR ); + +private: + + /** + * Function parseInt + * parses an integer and constrains it between two values. + * @param aMin is the smallest return value. + * @param aMax is the largest return value. + * @return int - the parsed integer. + */ + int parseInt( int aMin, int aMax ); + + /** + * Function parseDouble + * parses a double + * @return double - the parsed double. + */ + double parseDouble(); + + void parseSetup() throw( IO_ERROR, PARSE_ERROR ); + void parseGraphic( WORKSHEET_DATAITEM * aItem ) throw( IO_ERROR, PARSE_ERROR ); + void parseText( WORKSHEET_DATAITEM_TEXT * aItem ) throw( IO_ERROR, PARSE_ERROR ); + void parseCoordinate( POINT_COORD& aCoord) throw( IO_ERROR, PARSE_ERROR ); +}; + +// PCB_PLOT_PARAMS_PARSER + +PAGE_LAYOUT_READER_PARSER::PAGE_LAYOUT_READER_PARSER( const char* aLine, const wxString& aSource ) : + PAGE_LAYOUT_READER_LEXER( aLine, aSource ) +{ + m_defaultTextSize.x = m_defaultTextSize.y = TB_DEFAULT_TEXTSIZE; + m_defaultLineWidth = 0.0; + m_defaulTextLineWidth = 0.0; +} + + +void PAGE_LAYOUT_READER_PARSER::Parse( WORKSHEET_LAYOUT* aLayout ) + throw( PARSE_ERROR, IO_ERROR ) +{ + T token; + WORKSHEET_DATAITEM * item; + + LOCALE_IO toggle; + + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + if( token == T_LEFT ) + token = NextTok(); + + if( token == T_page_layout ) + continue; + + switch( token ) + { + case T_setup: // Defines default values for graphic items + parseSetup(); + break; + + case T_line: + item = new WORKSHEET_DATAITEM( WORKSHEET_DATAITEM::WS_SEGMENT ); + parseGraphic( item ); + aLayout->Append( item ); + break; + + case T_rect: + item = new WORKSHEET_DATAITEM( WORKSHEET_DATAITEM::WS_RECT ); + parseGraphic( item ); + aLayout->Append( item ); + break; + + case T_tbtext: + NeedSYMBOLorNUMBER(); + item = new WORKSHEET_DATAITEM_TEXT( FromUTF8() ); + parseText( (WORKSHEET_DATAITEM_TEXT*) item ); + aLayout->Append( item ); + break; + + default: + Unexpected( CurText() ); + break; + } + } +} + +void PAGE_LAYOUT_READER_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + switch( token ) + { + case T_LEFT: + break; + + case T_linewidth: + m_defaultLineWidth = parseDouble(); + NeedRIGHT(); + break; + + case T_textsize: + m_defaultTextSize.x = parseDouble(); + m_defaultTextSize.y = parseDouble(); + NeedRIGHT(); + break; + + case T_textlinewidth: + m_defaulTextLineWidth = parseDouble(); + NeedRIGHT(); + break; + + default: + Unexpected( CurText() ); + break; + } + } +} + +void PAGE_LAYOUT_READER_PARSER::parseGraphic( WORKSHEET_DATAITEM * aItem ) + throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + + aItem->m_LineWidth = m_defaultLineWidth; + + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_comment: // Comment, search the closing ')' + while( ( token = NextTok() ) != T_RIGHT && token != T_EOF ); + break; + + case T_start: + parseCoordinate( aItem->m_Pos ); + break; + + case T_end: + parseCoordinate( aItem->m_End ); + break; + + case T_repeat: + aItem->m_RepeatCount = parseInt( -1, 100 ); + NeedRIGHT(); + break; + + case T_incrx: + aItem->m_IncrementVector.x = parseDouble(); + NeedRIGHT(); + break; + + case T_incry: + aItem->m_IncrementVector.y = parseDouble(); + NeedRIGHT(); + break; + + case T_linewidth: + aItem->m_LineWidth = parseDouble(); + NeedRIGHT(); + break; + + default: + Unexpected( CurText() ); + break; + } + } +} + + +void PAGE_LAYOUT_READER_PARSER::parseText( WORKSHEET_DATAITEM_TEXT* aItem ) + throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + + aItem->m_TextSize = m_defaultTextSize; + aItem->m_LineWidth = m_defaulTextLineWidth; + + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_comment: // Comment, search the closing ')' + while( ( token = NextTok() ) != T_RIGHT && token != T_EOF ); + break; + + case T_pos: + parseCoordinate( aItem->m_Pos ); + break; + + case T_repeat: + aItem->m_RepeatCount = parseInt( -1, 100 ); + NeedRIGHT(); + break; + + case T_incrx: + aItem->m_IncrementVector.x = parseDouble(); + NeedRIGHT(); + break; + + case T_incry: + aItem->m_IncrementVector.y = parseDouble(); + NeedRIGHT(); + break; + + case T_incrlabel: + aItem->m_IncrementLabel = parseInt(INT_MIN, INT_MAX); + NeedRIGHT(); + break; + + case T_maxlen: + aItem->m_BoundingBoxSize.x = parseDouble(); + NeedRIGHT(); + break; + + case T_maxheight: + aItem->m_BoundingBoxSize.y = parseDouble(); + NeedRIGHT(); + break; + + case T_font: + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + switch( token ) + { + case T_LEFT: + break; + + case T_bold: + aItem->m_Flags |= USE_BOLD; + break; + + case T_italic: + aItem->m_Flags |= USE_ITALIC; + break; + + case T_size: + aItem->m_TextSize.x = parseDouble(); + aItem->m_TextSize.y = parseDouble(); + NeedRIGHT(); + break; + + case T_linewidth: + aItem->m_LineWidth = parseDouble(); + NeedRIGHT(); + break; + + default: + Unexpected( CurText() ); + break; + } + } + break; + + case T_justify: + while( ( token = NextTok() ) != T_RIGHT ) + { + if( token == T_EOF) + break; + + switch( token ) + { + case T_center: + aItem->m_Hjustify = GR_TEXT_HJUSTIFY_CENTER; + aItem->m_Vjustify = GR_TEXT_VJUSTIFY_CENTER; + break; + + case T_left: + aItem->m_Hjustify = GR_TEXT_HJUSTIFY_LEFT; + break; + + case T_right: + aItem->m_Hjustify = GR_TEXT_HJUSTIFY_RIGHT; + break; + + case T_top: + aItem->m_Vjustify = GR_TEXT_VJUSTIFY_TOP; + break; + + case T_bottom: + aItem->m_Vjustify = GR_TEXT_VJUSTIFY_BOTTOM; + break; + + default: + Unexpected( CurText() ); + break; + } + } + break; + + case T_rotate: + aItem->m_Orient = parseDouble(); + NeedRIGHT(); + break; + + default: + Unexpected( CurText() ); + break; + } + } +} + +// parse an expression like " 25 1 ltcorner)" +void PAGE_LAYOUT_READER_PARSER::parseCoordinate( POINT_COORD& aCoord) + throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + + aCoord.m_Pos.x = parseDouble(); + aCoord.m_Pos.y = parseDouble(); + + while( ( token = NextTok() ) != T_RIGHT ) + { + switch( token ) + { + case T_ltcorner: + aCoord.m_Anchor = LT_CORNER; // left top corner + break; + + case T_lbcorner: + aCoord.m_Anchor = LB_CORNER; // left bottom corner + break; + + case T_rbcorner: + aCoord.m_Anchor = RB_CORNER; // right bottom corner + break; + + case T_rtcorner: + aCoord.m_Anchor = RT_CORNER; // right top corner + break; + + default: + Unexpected( CurText() ); + break; + } + } +} + +int PAGE_LAYOUT_READER_PARSER::parseInt( int aMin, int aMax ) +{ + T token = NextTok(); + + if( token != T_NUMBER ) + Expecting( T_NUMBER ); + + int val = atoi( CurText() ); + + if( val < aMin ) + val = aMin; + else if( val > aMax ) + val = aMax; + + return val; +} + + +double PAGE_LAYOUT_READER_PARSER::parseDouble() +{ + T token = NextTok(); + + if( token != T_NUMBER ) + Expecting( T_NUMBER ); + + double val = strtod( CurText(), NULL ); + + return val; +} + + +void WORKSHEET_LAYOUT::SetDefaultLayout() +{ + PAGE_LAYOUT_READER_PARSER lp_parser( defaultPageLayout, "default page" ); + + try + { + lp_parser.Parse( this ); + } + catch( IO_ERROR ioe ) + { + wxLogMessage( ioe.errorText ); + } +} diff --git a/common/page_layout_reader.keywords b/common/page_layout_reader.keywords new file mode 100644 index 0000000000..83e312dfb9 --- /dev/null +++ b/common/page_layout_reader.keywords @@ -0,0 +1,35 @@ +page_layout +setup +linewidth +textlinewidth +textsize +comment +line +rect +polygon +tbtext +ltcorner +lbcorner +rbcorner +rtcorner +name +pos +start +end +maxlen +maxheight +font +bold +italic +size +justify +left +center +right +top +bottom +rotate +repeat +incrx +incry +incrlabel diff --git a/common/title_block_shapes.cpp b/common/title_block_shapes.cpp index b00f95c49a..f9419894b9 100644 --- a/common/title_block_shapes.cpp +++ b/common/title_block_shapes.cpp @@ -1,5 +1,5 @@ /** - * @file title_block_shapes.cpp + * @file title_block_shape.cpp * @brief description of graphic items and texts to build a title block */ @@ -39,265 +39,157 @@ #include #include -#define GRID_REF_W Mm2mils( 1.8 ) // height of the band reference grid -#define TEXTSIZE Mm2mils( 1.5 ) // worksheet text size -#define FRMREF_TXTSIZE Mm2mils( 1.3 ) // worksheet frame reference text size -#define VARIABLE_BLOCK_START_POSITION (TEXTSIZE * 10) - -// The coordinates below are relative to the bottom right corner of page and -// will be subtracted from this origin. -#define BLOCK_OX Mm2mils( 106 ) -#define BLOCK_KICAD_VERSION_X BLOCK_OX - TEXTSIZE -#define BLOCK_KICAD_VERSION_Y TEXTSIZE -#define BLOCK_REV_X Mm2mils( 22 ) -#define BLOCK_REV_Y (TEXTSIZE * 3) -#define BLOCK_DATE_X BLOCK_OX - (TEXTSIZE * 15) -#define BLOCK_DATE_Y (TEXTSIZE * 3) -#define BLOCK_ID_SHEET_X Mm2mils( 22 ) -#define BLOCK_ID_SHEET_Y TEXTSIZE -#define BLOCK_SIZE_SHEET_X BLOCK_OX - TEXTSIZE -#define BLOCK_SIZE_SHEET_Y (TEXTSIZE * 3) -#define BLOCK_TITLE_X BLOCK_OX - TEXTSIZE -#define BLOCK_TITLE_Y (TEXTSIZE * 5) -#define BLOCK_FULLSHEETNAME_X BLOCK_OX - TEXTSIZE -#define BLOCK_FULLSHEETNAME_Y (TEXTSIZE * 7) -#define BLOCK_FILENAME_X BLOCK_OX - TEXTSIZE -#define BLOCK_FILENAME_Y (TEXTSIZE * 9) -#define BLOCK_COMMENT_X BLOCK_OX - TEXTSIZE -#define BLOCK_COMPANY_Y (TEXTSIZE * 11) -#define BLOCK_COMMENT1_Y (TEXTSIZE * 13) -#define BLOCK_COMMENT2_Y (TEXTSIZE * 15) -#define BLOCK_COMMENT3_Y (TEXTSIZE * 17) -#define BLOCK_COMMENT4_Y (TEXTSIZE * 19) +extern void SetDataList( WORKSHEET_LAYOUT& aDataList ); -// Text attributes set in m_Flags (ORed bits) - #define USE_BOLD 1 // has meaning for texts - #define USE_THICK_LINE 1 // equivalent to bold for lines - #define USE_ITALIC 2 // has meaning for texts - #define USE_TEXT_COLOR 4 - #define SET_UPPER_LIMIT 8 // Flag used to calculate variable position items - -// Work sheet structure type definitions. -enum TypeKi_WorkSheetData { - WS_TEXT, - WS_SEGMENT, - WS_UPPER_SEGMENT, - WS_LEFT_SEGMENT -}; - - -// superior horizontal segment: should be after comments -// to know the exact position -Ki_WorkSheetData WS_MostUpperLine = +WORKSHEET_DATAITEM_TEXT::WORKSHEET_DATAITEM_TEXT( const wxChar* aTextBase ) : + WORKSHEET_DATAITEM( WS_TEXT ) { - WS_UPPER_SEGMENT, - NULL, - BLOCK_OX, TEXTSIZE * 16, - 0, TEXTSIZE * 16, - NULL -}; + m_TextBase = aTextBase; + m_IncrementLabel = 1; + m_Hjustify = GR_TEXT_HJUSTIFY_LEFT; + m_Vjustify = GR_TEXT_VJUSTIFY_CENTER; + m_Orient = 0.0; + m_TextSize.x = m_TextSize.y = TB_DEFAULT_TEXTSIZE; +} -// Left vertical segment: should be after comments -// to know the exact position -Ki_WorkSheetData WS_MostLeftLine = +void WORKSHEET_DATAITEM_TEXT::TransfertSetupToGraphicText( WS_DRAW_ITEM_TEXT* aGText ) { - WS_LEFT_SEGMENT, - &WS_MostUpperLine, - BLOCK_OX, TEXTSIZE * 16, - BLOCK_OX, 0, - NULL -}; + aGText->SetHorizJustify( m_Hjustify ) ; + aGText->SetVertJustify( m_Vjustify ); + aGText->SetOrientation( m_Orient * 10 ); // graphic text orient unit = 0.1 degree +} -// horizontal segment between filename and comments -Ki_WorkSheetData WS_SeparatorLine = +void WORKSHEET_DATAITEM_TEXT::IncrementLabel( int aIncr ) { - WS_SEGMENT, - &WS_MostLeftLine, - BLOCK_OX, VARIABLE_BLOCK_START_POSITION, - 0, VARIABLE_BLOCK_START_POSITION, - NULL -}; + wxChar lbchar = m_TextBase[0]; + if( lbchar >= '0' && lbchar <= '9' ) + // A number is expected: + m_FullText.Printf( wxT("%d"), aIncr + lbchar - '0' ); + else + m_FullText.Printf( wxT("%c"), aIncr + lbchar ); +} -Ki_WorkSheetData WS_Date = +void WORKSHEET_DATAITEM_TEXT::SetConstrainedTextSize() { - WS_TEXT, - &WS_SeparatorLine, - BLOCK_DATE_X, BLOCK_DATE_Y, - 0, 0, - wxT( "Date: %D" ) -}; + m_ConstrainedTextSize = m_TextSize; -Ki_WorkSheetData WS_Licence = + if( m_BoundingBoxSize.x ) + { + bool italic = (m_Flags & USE_ITALIC) != 0; + int linewidth = 0; + int lenMsg = ReturnGraphicTextWidth( m_FullText, m_TextSize.x, italic, linewidth ); + if( lenMsg > m_BoundingBoxSize.x ) + m_ConstrainedTextSize.x = m_TextSize.x * m_BoundingBoxSize.x / lenMsg; + } + + if( m_BoundingBoxSize.y ) + { + if( m_ConstrainedTextSize.y > m_BoundingBoxSize.y ) + m_ConstrainedTextSize.y = m_BoundingBoxSize.y; + } +} + +const DPOINT WORKSHEET_DATAITEM::GetStartPos( int ii ) const { - WS_TEXT, - &WS_Date, - BLOCK_KICAD_VERSION_X,BLOCK_KICAD_VERSION_Y, - 0, - 0, - wxT("%K") // Kicad version -}; + DPOINT pos; + pos.x = m_Pos.m_Pos.x + ( m_IncrementVector.x * ii ); + pos.y = m_Pos.m_Pos.y + ( m_IncrementVector.y * ii ); -Ki_WorkSheetData WS_Revision = + switch( m_Pos.m_Anchor ) + { + case RB_CORNER: // right bottom corner + pos = m_RB_Corner - pos; + break; + + case RT_CORNER: // right top corner + pos.x = m_RB_Corner.x - pos.x; + pos.y = m_LT_Corner.y + pos.y; + break; + + case LB_CORNER: // left bottom corner + pos.x = m_LT_Corner.x + pos.x; + pos.y = m_RB_Corner.y - pos.y; + break; + + case LT_CORNER: // left top corner + pos = m_LT_Corner + pos; + break; + } + + return pos; +} + +const wxPoint WORKSHEET_DATAITEM::GetStartPosUi( int ii ) const { - WS_TEXT, - &WS_Licence, - BLOCK_REV_X, BLOCK_REV_Y, - 0, 0, - wxT( "Rev: %R" ), - USE_BOLD -}; + DPOINT pos = GetStartPos( ii ); + pos = pos * m_WSunits2Iu; + return wxPoint( int(pos.x), int(pos.y) ); +} -Ki_WorkSheetData WS_SizeSheet = +const DPOINT WORKSHEET_DATAITEM::GetEndPos( int ii ) const { - WS_TEXT, - &WS_Revision, - BLOCK_SIZE_SHEET_X,BLOCK_SIZE_SHEET_Y, - 0, 0, - wxT( "Size: %Z" ) // Paper format name -}; + DPOINT pos; + pos.x = m_End.m_Pos.x + ( m_IncrementVector.x * ii ); + pos.y = m_End.m_Pos.y + ( m_IncrementVector.y * ii ); + switch( m_End.m_Anchor ) + { + case RB_CORNER: // right bottom corner + pos = m_RB_Corner - pos; + break; -Ki_WorkSheetData WS_IdentSheet = + case RT_CORNER: // right top corner + pos.x = m_RB_Corner.x - pos.x; + pos.y = m_LT_Corner.y + pos.y; + break; + + case LB_CORNER: // left bottom corner + pos.x = m_LT_Corner.x + pos.x; + pos.y = m_RB_Corner.y - pos.y; + break; + + case LT_CORNER: // left top corner + pos = m_LT_Corner + pos; + break; + } + + return pos; +} + +const wxPoint WORKSHEET_DATAITEM::GetEndPosUi( int ii ) const { - WS_TEXT, - &WS_SizeSheet, - BLOCK_ID_SHEET_X,BLOCK_ID_SHEET_Y, - 0, 0, - wxT( "Id: %S/%N" ) -}; + DPOINT pos = GetEndPos( ii ); + pos = pos * m_WSunits2Iu; + return wxPoint( int(pos.x), int(pos.y) ); +} -Ki_WorkSheetData WS_Title = + +bool WORKSHEET_DATAITEM::IsInsidePage( int ii ) const { - WS_TEXT, - &WS_IdentSheet, - BLOCK_TITLE_X, BLOCK_TITLE_Y, - 0, 0, - wxT( "Title: %T" ), - USE_BOLD -}; + DPOINT pos = GetStartPos( ii ); -Ki_WorkSheetData WS_SheetFilename = -{ - WS_TEXT, - &WS_Title, - BLOCK_FILENAME_X, BLOCK_FILENAME_Y, - 0, 0, - wxT( "File: %F" ) -}; + if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x ) + return false; -Ki_WorkSheetData WS_FullSheetName = -{ - WS_TEXT, - &WS_SheetFilename, - BLOCK_FULLSHEETNAME_X,BLOCK_FULLSHEETNAME_Y, - 0, - 0, - wxT( "Sheet: %P" ) // Full sheet name (sheet path) -}; + if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y ) + return false; -Ki_WorkSheetData WS_Company = -{ - WS_TEXT, - &WS_FullSheetName, - BLOCK_COMMENT_X,BLOCK_COMPANY_Y, - 0, 0, - wxT("%Y"), // Company name - USE_BOLD | SET_UPPER_LIMIT | USE_TEXT_COLOR -}; + pos = GetEndPos( ii ); -Ki_WorkSheetData WS_Comment1 = -{ - WS_TEXT, - &WS_Company, - BLOCK_COMMENT_X,BLOCK_COMMENT1_Y, - 0, 0, - wxT("%C1"), // Comment 1 - SET_UPPER_LIMIT | USE_TEXT_COLOR -}; + if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x ) + return false; -Ki_WorkSheetData WS_Comment2 = -{ - WS_TEXT, - &WS_Comment1, - BLOCK_COMMENT_X,BLOCK_COMMENT2_Y, - 0, 0, - wxT("%C2"), // Comment 2 - SET_UPPER_LIMIT | USE_TEXT_COLOR -}; + if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y ) + return false; -Ki_WorkSheetData WS_Comment3 = -{ - WS_TEXT, - &WS_Comment2, - BLOCK_COMMENT_X,BLOCK_COMMENT3_Y, - 0, 0, - wxT("%C3"), // Comment 3 - SET_UPPER_LIMIT | USE_TEXT_COLOR -}; + return true; +} -Ki_WorkSheetData WS_Comment4 = -{ - WS_TEXT, - &WS_Comment3, - BLOCK_COMMENT_X, BLOCK_COMMENT4_Y, - 0, 0, - wxT("%C4"), // Comment 4 - SET_UPPER_LIMIT | USE_TEXT_COLOR -}; +double WORKSHEET_DATAITEM::m_WSunits2Iu = 1.0; +DPOINT WORKSHEET_DATAITEM::m_RB_Corner; +DPOINT WORKSHEET_DATAITEM::m_LT_Corner; - -// horizontal segment above COMPANY NAME -Ki_WorkSheetData WS_Segm3 = -{ - WS_SEGMENT, - &WS_Comment4, - BLOCK_OX, TEXTSIZE * 6, - 0, TEXTSIZE * 6, - NULL -}; - - -// vertical segment of the left REV and SHEET -Ki_WorkSheetData WS_Segm4 = -{ - WS_SEGMENT, - &WS_Segm3, - BLOCK_REV_X + TEXTSIZE,TEXTSIZE * 4, - BLOCK_REV_X + TEXTSIZE, 0, - NULL -}; - - -Ki_WorkSheetData WS_Segm5 = -{ - WS_SEGMENT, - &WS_Segm4, - BLOCK_OX, TEXTSIZE * 2, - 0, TEXTSIZE * 2, - NULL -}; - - -Ki_WorkSheetData WS_Segm6 = -{ - WS_SEGMENT, - &WS_Segm5, - BLOCK_OX, TEXTSIZE * 4, - 0, TEXTSIZE * 4, - NULL -}; - - -Ki_WorkSheetData WS_Segm7 = -{ - WS_SEGMENT, - &WS_Segm6, - BLOCK_OX - (TEXTSIZE * 11),TEXTSIZE * 4, - BLOCK_OX - (TEXTSIZE * 11),TEXTSIZE * 2, - NULL -}; - -#include +WORKSHEET_LAYOUT dataList; // The layout shape void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList( const wxString& aPaperFormat, @@ -306,178 +198,126 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList( const TITLE_BLOCK& aTitleBlock, EDA_COLOR_T aLineColor, EDA_COLOR_T aTextColor ) { - wxSize textsize( TEXTSIZE * m_milsToIu, TEXTSIZE * m_milsToIu ); - wxSize size_ref( FRMREF_TXTSIZE * m_milsToIu, - FRMREF_TXTSIZE * m_milsToIu ); - wxString msg; + #define milsTomm (25.4/1000) m_titleBlock = &aTitleBlock, m_paperFormat = &aPaperFormat, m_fileName = &aFileName, m_sheetFullName = &aSheetPathHumanReadable; + // Build the basic layout shape, if the layout list is empty + if( dataList.GetCount() == 0 ) + dataList.SetDefaultLayout(); + + WORKSHEET_DATAITEM::m_WSunits2Iu = m_milsToIu / milsTomm; // Left top corner position - wxPoint lt_corner; + DPOINT lt_corner; lt_corner.x = m_LTmargin.x; lt_corner.y = m_LTmargin.y; + WORKSHEET_DATAITEM::m_LT_Corner = lt_corner * milsTomm; // Right bottom corner position - wxPoint rb_corner; + DPOINT rb_corner; rb_corner.x = m_pageSize.x - m_RBmargin.x; rb_corner.y = m_pageSize.y - m_RBmargin.y; - - // Draw the border. - int ii, jj, ipas, gxpas, gypas; - - wxPoint pos = lt_corner; - wxPoint end = rb_corner; - for( ii = 0; ii < 2; ii++ ) - { - Append( new WS_DRAW_ITEM_RECT( - wxPoint( pos.x * m_milsToIu, pos.y * m_milsToIu ), - wxPoint( end.x * m_milsToIu, end.y * m_milsToIu ), - m_penSize, aLineColor ) ); - - pos.x += GRID_REF_W; - pos.y += GRID_REF_W; - end.x -= GRID_REF_W; - end.y -= GRID_REF_W; - } - - ipas = ( rb_corner.x - lt_corner.x ) / PAS_REF; - gxpas = ( rb_corner.x - lt_corner.x ) / ipas; - - for( ii = lt_corner.x + gxpas, jj = 1; ipas > 0; ii += gxpas, jj++, ipas-- ) - { - msg.Printf( wxT( "%d" ), jj ); - - if( ii < rb_corner.x - PAS_REF / 2 ) - { - Append( new WS_DRAW_ITEM_LINE( - wxPoint( ii * m_milsToIu, lt_corner.y * m_milsToIu ), - wxPoint( ii * m_milsToIu, ( lt_corner.y + GRID_REF_W ) * m_milsToIu ), - m_penSize, aLineColor ) ); - } - - Append( new WS_DRAW_ITEM_TEXT( msg, - wxPoint( ( ii - gxpas / 2 ) * m_milsToIu, - ( lt_corner.y + GRID_REF_W / 2 ) * m_milsToIu ), - size_ref, m_penSize, aLineColor ) ); - - if( ii < rb_corner.x - PAS_REF / 2 ) - { - Append( new WS_DRAW_ITEM_LINE( - wxPoint( ii * m_milsToIu, rb_corner.y * m_milsToIu ), - wxPoint( ii * m_milsToIu, (rb_corner.y - GRID_REF_W ) * m_milsToIu ), - m_penSize, aLineColor ) ); - } - - Append( new WS_DRAW_ITEM_TEXT( msg, - wxPoint( ( ii - gxpas / 2 ) * m_milsToIu, - ( rb_corner.y - GRID_REF_W / 2) * m_milsToIu ), - size_ref, m_penSize, aLineColor ) ); - } - - ipas = ( rb_corner.y - lt_corner.y ) / PAS_REF; - gypas = ( rb_corner.y - lt_corner.y ) / ipas; - - for( ii = lt_corner.y + gypas, jj = 0; ipas > 0; ii += gypas, jj++, ipas-- ) - { - if( jj < 26 ) - msg.Printf( wxT( "%c" ), jj + 'A' ); - else // I hope 52 identifiers are enough... - msg.Printf( wxT( "%c" ), 'a' + jj - 26 ); - - if( ii < rb_corner.y - PAS_REF / 2 ) - { - Append( new WS_DRAW_ITEM_LINE( - wxPoint( lt_corner.x * m_milsToIu, ii * m_milsToIu ), - wxPoint( ( lt_corner.x + GRID_REF_W ) * m_milsToIu, ii * m_milsToIu ), - m_penSize, aLineColor ) ); - } - - Append( new WS_DRAW_ITEM_TEXT( msg, - wxPoint( ( lt_corner.x + GRID_REF_W / 2 ) * m_milsToIu, - ( ii - gypas / 2 ) * m_milsToIu ), - size_ref, m_penSize, aLineColor ) ); - - if( ii < rb_corner.y - PAS_REF / 2 ) - { - Append( new WS_DRAW_ITEM_LINE( - wxPoint( rb_corner.x * m_milsToIu, ii * m_milsToIu ), - wxPoint( ( rb_corner.x - GRID_REF_W ) * m_milsToIu, ii * m_milsToIu ), - m_penSize, aLineColor ) ); - } - - Append( new WS_DRAW_ITEM_TEXT( msg, - wxPoint( ( rb_corner.x - GRID_REF_W / 2 ) * m_milsToIu, - ( ii - gxpas / 2 ) * m_milsToIu ), - size_ref, m_penSize, aLineColor ) ); - } - - int upperLimit = VARIABLE_BLOCK_START_POSITION; - rb_corner.x -= GRID_REF_W; - rb_corner.y -= GRID_REF_W; + WORKSHEET_DATAITEM::m_RB_Corner = rb_corner * milsTomm; WS_DRAW_ITEM_TEXT* gtext; - Ki_WorkSheetData* WsItem; int pensize; bool bold; bool italic = false; EDA_COLOR_T color; - for( WsItem = &WS_Segm7; WsItem != NULL; WsItem = WsItem->Pnext ) + for( unsigned ii = 0; ; ii++ ) { - pos.x = (rb_corner.x - WsItem->m_Posx) * m_milsToIu; - pos.y = (rb_corner.y - WsItem->m_Posy) * m_milsToIu; + WORKSHEET_DATAITEM* wsItem = dataList.GetItem( ii ); - msg.Empty(); + if( wsItem == NULL ) + break; - if( WsItem->m_Type == WS_TEXT && WsItem->m_TextBase ) - msg = BuildFullText( WsItem->m_TextBase ); - - switch( WsItem->m_Type ) + switch( wsItem->m_Type ) { - case WS_TEXT: - if( msg.IsEmpty() ) + case WORKSHEET_DATAITEM::WS_TEXT: + { + WORKSHEET_DATAITEM_TEXT * wsText = (WORKSHEET_DATAITEM_TEXT*)wsItem; + wsText->m_FullText = BuildFullText( wsText->m_TextBase ); + if( wsText->m_FullText.IsEmpty() ) break; + bold = false; - pensize = m_penSize; + pensize = wsText->GetPenSizeUi(); + + if( pensize == 0 ) + pensize = m_penSize; + color = aLineColor; - if( WsItem->m_Flags & USE_TEXT_COLOR ) + + if( wsText->m_Flags & USE_TEXT_COLOR ) color = aTextColor; - if( WsItem->m_Flags & USE_BOLD ) + wsText->SetConstrainedTextSize(); + wxSize textsize; + + textsize.x = KiROUND( wsText->m_ConstrainedTextSize.x + * WORKSHEET_DATAITEM::m_WSunits2Iu ); + textsize.y = KiROUND( wsText->m_ConstrainedTextSize.y + * WORKSHEET_DATAITEM::m_WSunits2Iu ); + + if( wsText->m_Flags & USE_BOLD ) { bold = true; pensize = GetPenSizeForBold( std::min( textsize.x, textsize.y ) ); } - Append( gtext = new WS_DRAW_ITEM_TEXT( msg, pos, textsize, - pensize, color, italic, bold ) ); - gtext->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); - if( WsItem->m_Flags & SET_UPPER_LIMIT ) - upperLimit = std::max( upperLimit, WsItem->m_Posy + TEXTSIZE ); + for( int jj = 0; jj < wsText->m_RepeatCount; ) + { + if( ! wsText->IsInsidePage( jj ) ) + break; + Append( gtext = new WS_DRAW_ITEM_TEXT( wsText->m_FullText, + wsText->GetStartPosUi( jj ), + textsize, + pensize, color, italic, bold ) ); + wsText->TransfertSetupToGraphicText( gtext ); + + jj++; + if( wsText->m_RepeatCount > 1 ) // Try to increment label + wsText->IncrementLabel( jj ); + } + } break; - case WS_UPPER_SEGMENT: + case WORKSHEET_DATAITEM::WS_SEGMENT: + pensize = wsItem->GetPenSizeUi(); - if( upperLimit == 0 ) - break; + if( pensize == 0 ) + pensize = m_penSize; - case WS_LEFT_SEGMENT: - WS_MostUpperLine.m_Posy = upperLimit; - WS_MostUpperLine.m_Endy = upperLimit; - WS_MostLeftLine.m_Posy = upperLimit; - pos.y = (rb_corner.y - WsItem->m_Posy) * m_milsToIu; + for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ ) + { + if( ! wsItem->IsInsidePage( jj ) ) + break; + Append( new WS_DRAW_ITEM_LINE( wsItem->GetStartPosUi( jj ), + wsItem->GetEndPosUi( jj ), + pensize, aLineColor ) ); + } + break; - case WS_SEGMENT: - end.x = rb_corner.x - WsItem->m_Endx; - end.y = rb_corner.y - WsItem->m_Endy; - Append( new WS_DRAW_ITEM_LINE( pos, - wxPoint( end.x * m_milsToIu, end.y * m_milsToIu ), - m_penSize, aLineColor ) ); + case WORKSHEET_DATAITEM::WS_RECT: + pensize = wsItem->GetPenSizeUi(); + + if( pensize == 0 ) + pensize = m_penSize; + + for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ ) + { + if( ! wsItem->IsInsidePage( jj ) ) + break; + + Append( new WS_DRAW_ITEM_RECT( wsItem->GetStartPosUi( jj ), + wsItem->GetEndPosUi( jj ), + pensize, aLineColor ) ); + } break; } } diff --git a/common/title_block_shapes_gost.cpp b/common/title_block_shapes_gost.cpp index e5ccad4ba9..86887d9597 100644 --- a/common/title_block_shapes_gost.cpp +++ b/common/title_block_shapes_gost.cpp @@ -1,5 +1,5 @@ /** - * @file title_block_shapes_gost.cpp + * @file title_block_shape_gost.h * @brief description of graphic items and texts to build a title block * using GOST standard */ @@ -43,6 +43,17 @@ #define TEXTSIZE 100 // worksheet text size +struct Ki_WorkSheetData +{ +public: + int m_Type; + Ki_WorkSheetData* Pnext; + int m_Posx, m_Posy; + int m_Endx, m_Endy; + const wxChar* m_TextBase; + int m_Flags; +}; + // Work sheet structure type definitions. enum TypeKi_WorkSheetData { WS_OSN, diff --git a/common/worksheet.cpp b/common/worksheet.cpp index a20c7dd877..f3fc9b5463 100644 --- a/common/worksheet.cpp +++ b/common/worksheet.cpp @@ -293,20 +293,17 @@ wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase ) format = aTextbase[++ii]; switch( format ) { + case '0': case '1': - msg += m_titleBlock->GetComment1(); - break; - case '2': - msg += m_titleBlock->GetComment2(); - break; - case '3': - msg += m_titleBlock->GetComment3(); - break; - case '4': - msg += m_titleBlock->GetComment4(); + case '5': + case '6': + case '7': + case '8': + case '9': + msg += m_titleBlock->GetComment( format - '0'); break; default: @@ -326,43 +323,42 @@ void TITLE_BLOCK::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aCont throw( IO_ERROR ) { // Don't write the title block information if there is nothing to write. - if( !m_title.IsEmpty() || !m_date.IsEmpty() || !m_revision.IsEmpty() - || !m_company.IsEmpty() || !m_comment1.IsEmpty() || !m_comment2.IsEmpty() - || !m_comment3.IsEmpty() || !m_comment4.IsEmpty() ) + bool isempty = true; + for( unsigned idx = 0; idx < m_tbTexts.GetCount(); idx++ ) + { + if( ! m_tbTexts[idx].IsEmpty() ) + { + isempty = false; + break; + } + } + + if( !isempty ) { aFormatter->Print( aNestLevel, "(title_block\n" ); - if( !m_title.IsEmpty() ) + if( !GetTitle().IsEmpty() ) aFormatter->Print( aNestLevel+1, "(title %s)\n", - aFormatter->Quotew( m_title ).c_str() ); + aFormatter->Quotew( GetTitle() ).c_str() ); - if( !m_date.IsEmpty() ) + if( !GetDate().IsEmpty() ) aFormatter->Print( aNestLevel+1, "(date %s)\n", - aFormatter->Quotew( m_date ).c_str() ); + aFormatter->Quotew( GetDate() ).c_str() ); - if( !m_revision.IsEmpty() ) + if( !GetRevision().IsEmpty() ) aFormatter->Print( aNestLevel+1, "(rev %s)\n", - aFormatter->Quotew( m_revision ).c_str() ); + aFormatter->Quotew( GetRevision() ).c_str() ); - if( !m_company.IsEmpty() ) + if( !GetCompany().IsEmpty() ) aFormatter->Print( aNestLevel+1, "(company %s)\n", - aFormatter->Quotew( m_company ).c_str() ); + aFormatter->Quotew( GetCompany() ).c_str() ); - if( !m_comment1.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment 1 %s)\n", - aFormatter->Quotew( m_comment1 ).c_str() ); - - if( !m_comment2.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment 2 %s)\n", - aFormatter->Quotew( m_comment2 ).c_str() ); - - if( !m_comment3.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment 3 %s)\n", - aFormatter->Quotew( m_comment3 ).c_str() ); - - if( !m_comment4.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment 4 %s)\n", - aFormatter->Quotew( m_comment4 ).c_str() ); + for( int ii = 0; ii < 3; ii++ ) + { + if( !GetComment(ii).IsEmpty() ) + aFormatter->Print( aNestLevel+1, "(comment %d %s)\n", ii+1, + aFormatter->Quotew( GetComment(1) ).c_str() ); + } aFormatter->Print( aNestLevel, ")\n\n" ); } diff --git a/include/class_title_block.h b/include/class_title_block.h index efbe13599c..785be8aab4 100644 --- a/include/class_title_block.h +++ b/include/class_title_block.h @@ -39,49 +39,94 @@ struct IO_ERROR; */ class TITLE_BLOCK { + // Texts are stored in wxArraystring. + // textsIdx gives the index of known texts in + // this array + enum textsIdx + { + titleIdx = 0, + dateIdx, + revisionIdx, + companyIdx, + m_commentIdx + }; + public: - // TITLE_BLOCK(); + + TITLE_BLOCK() {}; virtual ~TITLE_BLOCK() {}; // a virtual dtor seems needed to build // python lib without warning - void SetTitle( const wxString& aTitle ) { m_title = aTitle; } - const wxString& GetTitle() const { return m_title; } + void SetTitle( const wxString& aTitle ) + { + setTbText( titleIdx, aTitle ); + } + + const wxString& GetTitle() const + { + return getTbText( titleIdx );; + } /** * Function SetDate * sets the date field, and defaults to the current time and date. */ - void SetDate( const wxString& aDate ) { m_date = aDate; } - const wxString& GetDate() const { return m_date; } + void SetDate( const wxString& aDate ) + { + setTbText( dateIdx, aDate ); + } - void SetRevision( const wxString& aRevision ) { m_revision = aRevision; } - const wxString& GetRevision() const { return m_revision; } + const wxString& GetDate() const + { + return getTbText( dateIdx ); + } - void SetCompany( const wxString& aCompany ) { m_company = aCompany; } - const wxString& GetCompany() const { return m_company; } + void SetRevision( const wxString& aRevision ) + { + setTbText( revisionIdx, aRevision ); + } - void SetComment1( const wxString& aComment ) { m_comment1 = aComment; } - const wxString& GetComment1() const { return m_comment1; } + const wxString& GetRevision() const + { + return getTbText( revisionIdx ); + } - void SetComment2( const wxString& aComment ) { m_comment2 = aComment; } - const wxString& GetComment2() const { return m_comment2; } + void SetCompany( const wxString& aCompany ) + { + setTbText( companyIdx, aCompany ); + } - void SetComment3( const wxString& aComment ) { m_comment3 = aComment; } - const wxString& GetComment3() const { return m_comment3; } + const wxString& GetCompany() const + { + return getTbText( companyIdx ); + } + + void SetComment( int aIdx, const wxString& aComment ) + { + aIdx += m_commentIdx; + return setTbText( aIdx, aComment ); + } + + const wxString& GetComment( int aIdx ) const + { + aIdx += m_commentIdx; + return getTbText( aIdx ); + } + + // Only for old code compatibility. Will be removed later + void SetComment1( const wxString& aComment ) { SetComment( 0, aComment ); } + void SetComment2( const wxString& aComment ) { SetComment( 1, aComment ); } + void SetComment3( const wxString& aComment ) { SetComment( 2, aComment ); } + void SetComment4( const wxString& aComment ) { SetComment( 3, aComment ); } + const wxString& GetComment1( ) const { return GetComment( 0 ); } + const wxString& GetComment2( ) const { return GetComment( 1 ); } + const wxString& GetComment3( ) const { return GetComment( 2 ); } + const wxString& GetComment4( ) const { return GetComment( 3 ); } - void SetComment4( const wxString& aComment ) { m_comment4 = aComment; } - const wxString& GetComment4() const { return m_comment4; } void Clear() { - m_title.clear(); - m_date.clear(); - m_revision.clear(); - m_company.clear(); - m_comment1.clear(); - m_comment2.clear(); - m_comment3.clear(); - m_comment4.clear(); + m_tbTexts.Clear(); } /** @@ -97,14 +142,24 @@ public: throw( IO_ERROR ); private: - wxString m_title; - wxString m_date; - wxString m_revision; - wxString m_company; - wxString m_comment1; - wxString m_comment2; - wxString m_comment3; - wxString m_comment4; + wxArrayString m_tbTexts; + + void setTbText( int aIdx, const wxString& aText ) + { + if( (int)m_tbTexts.GetCount() <= aIdx ) + m_tbTexts.Add( wxEmptyString, aIdx + 1 - m_tbTexts.GetCount() ); + m_tbTexts[aIdx] = aText; + } + + const wxString& getTbText( int aIdx ) const + { + static const wxString m_emptytext; + + if( (int)m_tbTexts.GetCount() > aIdx ) + return m_tbTexts[aIdx]; + else + return m_emptytext; + } }; #endif // TITLE_BLOCK_H_ diff --git a/include/vector2d.h b/include/vector2d.h index 3968984df1..b2662b0505 100644 --- a/include/vector2d.h +++ b/include/vector2d.h @@ -27,7 +27,7 @@ #define VECTOR2D_H_ #include -#include +#include // For wxPoint definition /// Forward declaration for template friends diff --git a/include/worksheet.h b/include/worksheet.h index 6df596d889..0928963554 100644 --- a/include/worksheet.h +++ b/include/worksheet.h @@ -7,24 +7,15 @@ #ifndef WORKSHEET_H_ #define WORKSHEET_H_ -// Forwadr declarations: +#include // EDA_COLOR_T definition + +// Forward declarations: class EDA_DRAW_PANEL; class TITLE_BLOCK; class PAGE_INFO; #define PAS_REF 2000 // Pitch (in mils) of reference locations in worksheet -struct Ki_WorkSheetData -{ -public: - int m_Type; - Ki_WorkSheetData* Pnext; - int m_Posx, m_Posy; - int m_Endx, m_Endy; - const wxChar* m_TextBase; - int m_Flags; -}; - /** * Function DrawPageLayout is a core function to draw the page layout with * the frame and the basic inscriptions. diff --git a/include/worksheet_shape_builder.h b/include/worksheet_shape_builder.h index c0d27da722..740a2887db 100644 --- a/include/worksheet_shape_builder.h +++ b/include/worksheet_shape_builder.h @@ -7,6 +7,156 @@ #ifndef WORKSHEET_SHAPE_BUILDER_H #define WORKSHEET_SHAPE_BUILDER_H +#include +#include + +class WS_DRAW_ITEM_TEXT; // Forward declaration + +#define TB_DEFAULT_TEXTSIZE 1.5 // default worksheet text size in mm + +// Text attributes set in m_Flags (ORed bits) + #define USE_BOLD 1 // has meaning for texts + #define USE_THICK_LINE 1 // equivalent to bold for lines + #define USE_ITALIC 2 // has meaning for texts + #define USE_TEXT_COLOR 4 + #define SET_UPPER_LIMIT 8 // Flag used to calculate variable position items + +// A coordinate is relative to a page corner. +// Any of the 4 corners can be a reference. +// The default is the right bottom corner +enum corner_anchor +{ + RB_CORNER, // right bottom corner + RT_CORNER, // right top corner + LB_CORNER, // left bottom corner + LT_CORNER, // left top corner +}; + +// a coordinate point +// The position is always relative to the corner anchor +// Note the coordinate is from the anchor point +// to the opposite corner. +class POINT_COORD +{ +public: + DPOINT m_Pos; + int m_Anchor; +public: + POINT_COORD() { m_Anchor = RB_CORNER; } + POINT_COORD( DPOINT aPos, enum corner_anchor aAnchor = RB_CORNER ) + { + m_Pos = aPos; + m_Anchor = aAnchor; + } +}; + + +// Work sheet structure type definitions. +class WORKSHEET_DATAITEM +{ +public: + enum WS_ItemType { + WS_TEXT, + WS_SEGMENT, + WS_RECT + }; + WS_ItemType m_Type; + POINT_COORD m_Pos; + POINT_COORD m_End; + double m_LineWidth; + int m_Flags; + int m_RepeatCount; // repeat count for duplicate items + DPOINT m_IncrementVector; // For duplicate items: move vector + // for position increment + int m_IncrementLabel; + + static double m_WSunits2Iu; // conversion factor between + // ws units (mils) and draw/plot units + static DPOINT m_RB_Corner; // cordinates of the right bottom corner + // (ws units) + static DPOINT m_LT_Corner; // cordinates of the left top corner + // (ws units) + +public: + WORKSHEET_DATAITEM( WS_ItemType aType ) + { + m_Type = aType; + m_Flags = 0; + m_RepeatCount = 1; + m_IncrementLabel = 0; + m_LineWidth = 0.0; + } + + void SetStart( double aPosx, double aPosy, enum corner_anchor aAnchor = RB_CORNER ) + { + m_Pos.m_Pos.x = aPosx; + m_Pos.m_Pos.y = aPosy; + m_Pos.m_Anchor = aAnchor; + } + + void SetEnd( double aPosx, double aPosy, enum corner_anchor aAnchor = RB_CORNER ) + { + m_End.m_Pos.x = aPosx; + m_End.m_Pos.y = aPosy; + m_End.m_Anchor = aAnchor; + } + + const wxPoint GetStartPosUi( int ii = 0 ) const; + const wxPoint GetEndPosUi( int ii = 0 ) const; + const DPOINT GetStartPos( int ii = 0 ) const; + const DPOINT GetEndPos( int ii = 0 ) const; + bool IsInsidePage( int ii ) const; + int GetPenSizeUi() {return KiROUND( m_LineWidth * m_WSunits2Iu ); } +}; + +class WORKSHEET_DATAITEM_TEXT : public WORKSHEET_DATAITEM +{ +public: + wxString m_TextBase; // The basic text, with format symbols + wxString m_FullText; // The expanded text, shown on screen + int m_IncrementLabel; + double m_Orient; // Orientation in degrees + enum EDA_TEXT_HJUSTIFY_T m_Hjustify; + enum EDA_TEXT_VJUSTIFY_T m_Vjustify; + DSIZE m_TextSize; + DSIZE m_BoundingBoxSize; // When not null, this is the max + // size of the full text. + // the text size will be modified + // to keep the full text insite this + // bound. + DSIZE m_ConstrainedTextSize;// Actual text size, if constrained by + // the m_BoundingBoxSize constraint + +public: + WORKSHEET_DATAITEM_TEXT( const wxChar* aTextBase ); + + /** + * transfert the text justification and orientation + * to aGText + */ + void TransfertSetupToGraphicText( WS_DRAW_ITEM_TEXT* aGText ); + + /** + * Try to build text wihich is an increment of m_TextBase + * has meaning only if m_TextBase is a basic text (one char) + * If the basic char is a digit, build a number + * If the basic char is a letter, use the letter with ascii code + * aIncr + (basic char ascc code) + * @param aIncr = the increment value + * return the incremented label in m_FullText + */ + void IncrementLabel( int aIncr ); + + /** + * Calculates m_ConstrainedTextSize from m_TextSize + * to keep the X size and the full Y size of the text + * smaller than m_BoundingBoxSize + * if m_BoundingBoxSize.x or m_BoundingBoxSize.y > 0 + * if m_BoundingBoxSize.x or m_BoundingBoxSize.y == 0 + * the corresponding text size is not constrained + */ + void SetConstrainedTextSize(); +}; /* * Helper classes to handle basic graphic items used to raw/plot @@ -22,9 +172,11 @@ public: enum WS_DRAW_TYPE { wsg_line, wsg_rect, wsg_poly, wsg_text }; + protected: WS_DRAW_TYPE m_type; // wsg_line, wsg_rect, wsg_poly, wsg_text EDA_COLOR_T m_color; + protected: WS_DRAW_ITEM_BASE( WS_DRAW_TYPE aType, EDA_COLOR_T aColor ) { @@ -133,7 +285,8 @@ class WS_DRAW_ITEM_LIST wxSize m_pageSize; // the page size in mils double m_milsToIu; // the scalar to convert pages units ( mils) // to draw/plot units. - int m_penSize; // The line width for drawings. + int m_penSize; // The default line width for drawings. + // used when an item has a pen size = 0 int m_sheetNumber; // the value of the sheet number, for basic inscriptions int m_sheetCount; // the value of the number of sheets, in schematic // for basic inscriptions, in schematic @@ -298,4 +451,52 @@ public: }; +/** + * WORKSHEET_LAYOUT handles the grpahic items list to draw/plot + * the title block and other items (page references ... + */ +class WORKSHEET_LAYOUT +{ + std::vector m_list; + +public: + WORKSHEET_LAYOUT() {}; + ~WORKSHEET_LAYOUT() {ClearList(); } + + void ClearList() + { + for( unsigned ii = 0; ii < m_list.size(); ii++ ) + delete m_list[ii]; + } + + /** + * Add an item to the list of items + */ + void Append( WORKSHEET_DATAITEM* aItem ) + { + m_list.push_back( aItem ); + } + + /** + * @return the item from its index aIdx, or NULL if does not exist + */ + WORKSHEET_DATAITEM* GetItem( unsigned aIdx ) const + { + if( aIdx < m_list.size() ) + return m_list[aIdx]; + else + return NULL; + } + + /** + * @return the item count + */ + unsigned GetCount() const { return m_list.size(); } + + /** + * Fills the list with the default layout shape + */ + void SetDefaultLayout(); +}; + #endif // WORKSHEET_SHAPE_BUILDER_H diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 7fec74299a..181da820b7 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -64,37 +64,12 @@ static const wxString traceFootprintLibrary( wxT( "KicadFootprintLib" ) ); // Helper function to print a float number without using scientific notation // and no trailing 0 +// We want to avoid scientific notation in S-expr files (not easy to read) +// for floating numbers. +// So we cannot always just use the %g or the %f format to print a fp number +// this helper function uses the %f format when needed, or %g when %f is +// not well working and then removes trailing 0 -#if 0 -// Does not work for aValue < 0.0001 and > 0. -// Will need to support exponents in DSNLEXER if we get exponents > 16, i.e. the "precision". -std::string double2str( double aValue ) -{ - char buf[50]; - int len; - - if( aValue != 0.0 && fabs( aValue ) <= 0.0001 ) - { - len = sprintf( buf, "%.10f", aValue ); - - while( --len > 0 && buf[len] == '0' ) - buf[len] = '\0'; - - if( buf[len] == '.' ) - buf[len--] = '\0'; - - ++len; - } - else - { - len = sprintf( buf, "%.10g", mm ); - } - - return std::string( buf, len ); -} - -#else -// this one handles 0.00001 ok, and 1.222222222222222 ok, previous did not. std::string double2str( double aValue ) { char buf[50]; @@ -102,6 +77,8 @@ std::string double2str( double aValue ) if( aValue != 0.0 && fabs( aValue ) <= 0.0001 ) { + // For these small values, %f works fine, + // and %g gives an exponent len = sprintf( buf, "%.16f", aValue ); while( --len > 0 && buf[len] == '0' ) @@ -114,12 +91,13 @@ std::string double2str( double aValue ) } else { + // For these values, %g works fine, and sometimes %f + // gives a bad value (try aValue = 1.222222222222, with %.16f format!) len = sprintf( buf, "%.16g", aValue ); } return std::string( buf, len );; } -#endif /**