Commit f3b5ed43 authored by jean-pierre charras's avatar jean-pierre charras
Browse files

Added an *experimental* tool (bitmap2component) to create logos from .bmp...

Added an *experimental* tool (bitmap2component) to create logos from .bmp bitmaps. Added Potrace library to convert bitmaps to polygons
    This tool uses potarce library that converts a bitmap picture (.bmp or .pgm format) to a set of polygons.
    bitmap2component converts a bitmap to a .emp footprint (that can be imported by modedit) or a .lib component that can be    imported by libedit.
    See changelog for more info
parents 82aadca8 076832cd
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -4,6 +4,24 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with
email address.


2010-jun-10, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
Added an experimental tool (bitmap2component) to create logos from .bmp bitmaps. Added Potrace library to convert bitmaps to polygons
    This tool uses potarce library that converts a bitmap picture (.bmp or .pgm format) to a set of polygons.
    bitmap2component converts a bitmap to a .emp footprint (that can be imported by modedit) or a .lib component that can be
    imported by libedit.
    Note: imported bitmaps logos are vectored by potrace, so there is no pixelation effect.
    Scale is 1:1 for 300ppi pictures.
    bitmap2component currently runs only is command line mode
    run
        bitmap2component bitmapfile.bmp bitmapfile.lib 1 to create a schematic component logo
        (import this file using libedit)
        or
        bitmap2component bitmapfile.bmp bitmapfile.emp 1 to create a footprint logo
        (import this file using modedit)


2010-may-18, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++All:
+2 −0
Original line number Diff line number Diff line
@@ -187,6 +187,8 @@ add_subdirectory(kicad)
add_subdirectory(pcbnew)
add_subdirectory(polygon)
add_subdirectory(polygon/kbool/src)
add_subdirectory(potrace)
add_subdirectory(bitmap2component)

#############
# Resources #
+22 −0
Original line number Diff line number Diff line
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
                    ../potrace
                    ../polygon/kbool/include
                    )

set(BITMAP2COMPONENT_SRCS
    bitmap2component.cpp
    )

add_executable(bitmap2component WIN32 MACOSX_BUNDLE ${BITMAP2COMPONENT_SRCS} ${BITMAP2COMPONENT_RESOURCES})


target_link_libraries( bitmap2component potrace kbool )

if(APPLE)
    set_target_properties(bitmap2component PROPERTIES )
endif(APPLE)

install(TARGETS bitmap2component
        DESTINATION ${KICAD_BIN}
        COMPONENT binary)
+570 −0
Original line number Diff line number Diff line
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (C) 1992-2010 jean-pierre.charras
 * Copyright (C) 1992-2010 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 "kbool/booleng.h"

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <math.h>
#include <vector>

#include "potracelib.h"
#include "bitmap_io.h"
#include "auxiliary.h"


#ifndef max
    #define max( a, b ) ( ( (a) > (b) ) ? (a) : (b) )
  #endif
  #ifndef min
    #define min( a, b ) ( ( (a) < (b) ) ? (a) : (b) )
  #endif


enum output_format {
    POSTSCRIPT_FMT = 1,
    PCBNEW_FMT,
    EESCHEMA_FMT
};


/* Helper class th handle useful info to convert a bitmpa to
 *  a polygonal object description
 */
class BITMAPCONV_INFO
{
public:
    enum output_format m_Format;
    int m_PixmapWidth;
    int m_PixmapHeight;             // the bitmap size in pixels
    double             m_ScaleX;
    double             m_ScaleY;    // the conversion scale
    potrace_path_t*    m_Paths;     // the list of paths, from potrace (list of lines and bezier curves)
    FILE* m_Outfile;
public:
    BITMAPCONV_INFO();
};

static void BezierToPolyline( std::vector <potrace_dpoint_t>& aCornersBuffer,
                              potrace_dpoint_t                p1,
                              potrace_dpoint_t                p2,
                              potrace_dpoint_t                p3,
                              potrace_dpoint_t                p4 );

static void CreateOutputFile( BITMAPCONV_INFO& aInfo );

static const char* CmpName = "LOGO";


BITMAPCONV_INFO::BITMAPCONV_INFO()
{
    m_Format = POSTSCRIPT_FMT;
    m_PixmapWidth  = 0;
    m_PixmapHeight = 0;
    m_ScaleX  = 1.0;
    m_ScaleY  = 1.0;
    m_Paths   = NULL;
    m_Outfile = NULL;
}


/** Function ArmBoolEng
 * Initialise parameters used in kbool
 * @param aBooleng = pointer to the Bool_Engine to initialise
 * @param aConvertHoles = mode for holes when a boolean operation is made
 *   true: in resulting polygon, holes are linked into outer contours by double overlapping segments
 *   false: in resulting polygons, holes are not linked: they are separate polygons
 */
void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles )
{
    // set some global vals to arm the boolean engine

    // input points are scaled up with GetDGrid() * GetGrid()

    // DGRID is only meant to make fractional parts of input data which

    /*
     *  The input data scaled up with DGrid is related to the accuracy the user has in his input data.
     *  User data with a minimum accuracy of 0.001, means set the DGrid to 1000.
     *  The input data may contain data with a minimum accuracy much smaller, but by setting the DGrid
     *  everything smaller than 1/DGrid is rounded.
     *
     *  DGRID is only meant to make fractional parts of input data which can be
     *  doubles, part of the integers used in vertexes within the boolean algorithm.
     *  And therefore DGRID bigger than 1 is not usefull, you would only loose accuracy.
     *  Within the algorithm all input data is multiplied with DGRID, and the result
     *  is rounded to an integer.
     */
    double DGRID = 1000.0;      // round coordinate X or Y value in calculations to this (initial value = 1000.0 in kbool example)
                                // kbool uses DGRID to convert float user units to integer
                                // kbool unit = (int)(user unit * DGRID)
                                // Note: in kicad, coordinates are already integer so DGRID could be set to 1
                                // we can choose 1.0,
                                // but choose DGRID = 1000.0 solves some filling problems
//                             (perhaps because this allows a better precision in kbool internal calculations

    double MARGE = 1.0 / DGRID;         // snap with in this range points to lines in the intersection routines
                                        // should always be >= 1/DGRID  a  MARGE >= 10/DGRID is ok
                                        // this is also used to remove small segments and to decide when
                                        // two segments are in line. ( initial value = 0.001 )
                                        // For kicad we choose MARGE = 1/DGRID

    double CORRECTIONFACTOR = 0.0;      // correct the polygons by this number: used in BOOL_CORRECTION operation
                                        // this operation shrinks a polygon if CORRECTIONFACTOR < 0
                                        // or stretch it if CORRECTIONFACTOR > 0
                                        // the size change is CORRECTIONFACTOR (holes are correctly handled)
    double CORRECTIONABER = 1.0;        // the accuracy for the rounded shapes used in correction
    double ROUNDFACTOR    = 1.5;        // when will we round the correction shape to a circle
    double SMOOTHABER     = 10.0;       // accuracy when smoothing a polygon
    double MAXLINEMERGE   = 1000.0;     // leave as is, segments of this length in smoothen


    /*
     *    Grid makes sure that the integer data used within the algorithm has room for extra intersections
     *    smaller than the smallest number within the input data.
     *    The input data scaled up with DGrid is related to the accuracy the user has in his input data.
     *    Another scaling with Grid is applied on top of it to create space in the integer number for
     *    even smaller numbers.
     */
    int GRID = (int) 10000 / DGRID;       // initial value = 10000 in kbool example

    // But we use 10000/DGRID because the scalling is made
    // by DGRID on integer pcbnew units and
    // the global scalling ( GRID*DGRID) must be < 30000 to avoid
    // overflow in calculations (made in long long in kbool)
    if( GRID <= 1 )     // Cannot be null!
        GRID = 1;

    aBooleng->SetMarge( MARGE );
    aBooleng->SetGrid( GRID );
    aBooleng->SetDGrid( DGRID );
    aBooleng->SetCorrectionFactor( CORRECTIONFACTOR );
    aBooleng->SetCorrectionAber( CORRECTIONABER );
    aBooleng->SetSmoothAber( SMOOTHABER );
    aBooleng->SetMaxlinemerge( MAXLINEMERGE );
    aBooleng->SetRoundfactor( ROUNDFACTOR );
    aBooleng->SetWindingRule( true );           // This is the default kbool value

    if( aConvertHoles )
    {
#if 1                                                       // Can be set to 1 for kbool version >= 2.1, must be set to 0 for previous versions
        // SetAllowNonTopHoleLinking() exists only in kbool >= 2.1
        aBooleng->SetAllowNonTopHoleLinking( false );       // Default = , but i have problems (filling errors) when true
#endif
        aBooleng->SetLinkHoles( true );                     // holes will be connected by double overlapping segments
        aBooleng->SetOrientationEntryMode( false );         // all polygons are contours, not holes
    }
    else
    {
        aBooleng->SetLinkHoles( false );                // holes will not be connected by double overlapping segments
        aBooleng->SetOrientationEntryMode( true );      // holes are entered counter clockwise
    }
}


int main( int argc, char* argv[] )
{
    potrace_bitmap_t* potrace_bitmap = NULL;
    potrace_param_t*  param;
    potrace_state_t*  st;
    int   error;
    int fmt_option = '0';


    FILE* infile, * outfile = NULL;

    if( argc < 4 )
    {
        printf( "Usage:\nbitmap2component <infile_bitmap.ext> <outfile.ext> <0,1,2>\n" );
        printf( "  Allowed bitmap files formats are .bmp or .pgm\n" );
        printf( "output format:\n   0 = pcbnew.emp, 1 = eeschema.lib, 2 = ps\n" );
        return -1;
    }

    infile = fopen( argv[1], "r" );
    if( infile == NULL )
    {
        printf( "File %s could not be opened\n", argv[1] );
        return -2;
    }

    outfile = fopen( argv[2], "w" );
    if( outfile == NULL )
    {
        printf( "File %s could not be opened\n", argv[2] );
        return -2;
    }

    double threshold = 0.5;     // = 0 to 1.0

    error = bm_read( infile, threshold, &potrace_bitmap );
    if( error != 0 )
    {
        printf( "Bitmap %s could not be read\n", argv[1] );
        return -2;
    }

    if( !potrace_bitmap )
    {
        fprintf( stderr, "Error allocating bitmap: %s\n", strerror( errno ) );
        return 1;
    }

    /* set tracing parameters, starting from defaults */
    param = potrace_param_default();
    if( !param )
    {
        fprintf( stderr, "Error allocating parameters: %s\n", strerror( errno ) );
        return 1;
    }
    param->turdsize = 0;

    /* convert the bitmap to curves */
    st = potrace_trace( param, potrace_bitmap );
    if( !st || st->status != POTRACE_STATUS_OK )
    {
        fprintf( stderr, "Error tracing bitmap: %s\n", strerror( errno ) );
        return 1;
    }

    BITMAPCONV_INFO info;
    info.m_PixmapWidth  = potrace_bitmap->w;
    info.m_PixmapHeight = potrace_bitmap->h;     // the bitmap size in pixels
    info.m_Paths   = st->plist;
    info.m_Outfile = outfile;

    if( argc >= 4 )
        fmt_option = argv[3][0];
    switch( fmt_option )
    {
    case '2':
        info.m_Format = POSTSCRIPT_FMT;
        info.m_ScaleX = info.m_ScaleY = 1.0;        // the conversion scale
        /* output vector data, e.g. as a rudimentary EPS file */
        break;

    case '1':
        info.m_Format = EESCHEMA_FMT;
        info.m_ScaleX = info.m_ScaleY = 1000.0 / 300;        // the conversion scale
        break;

    case '0':
        info.m_Format = PCBNEW_FMT;
        info.m_ScaleX = 10000.0 / 300;        // the conversion scale
        info.m_ScaleY = -info.m_ScaleX;       // Y axis is top to bottom in modedit
        break;

    default:
        printf( "Unknown output format\n" );
        break;
    }

    CreateOutputFile( info );

    bm_free( potrace_bitmap );

    potrace_state_free( st );
    potrace_param_free( param );

    return 0;
}


static void OuputHeader( BITMAPCONV_INFO& aInfo )
{
    int Ypos = (int) ( aInfo.m_PixmapHeight / 2 * aInfo.m_ScaleY );
    int fieldSize;             // fields text size = 60 mils

    switch( aInfo.m_Format )
    {
    case POSTSCRIPT_FMT:
        /* output vector data, e.g. as a rudimentary EPS file */
        fprintf( aInfo.m_Outfile, "%%!PS-Adobe-3.0 EPSF-3.0\n" );
        fprintf( aInfo.m_Outfile, "%%%%BoundingBox: 0 0 %d %d\n",
                 aInfo.m_PixmapWidth, aInfo.m_PixmapHeight );
        fprintf( aInfo.m_Outfile, "gsave\n" );
        break;

    case PCBNEW_FMT:
        #define FIELD_LAYER 21
        fieldSize = 600;             // fields text size = 60 mils
        Ypos += fieldSize / 2;
        fprintf( aInfo.m_Outfile, "PCBNEW-LibModule-V1\n" );
        fprintf( aInfo.m_Outfile, "$INDEX\n%s\n$EndINDEX\n", CmpName );

        fprintf( aInfo.m_Outfile, "#\n# %s\n", CmpName );
        fprintf( aInfo.m_Outfile, "# pixmap w = %d, h = %d\n#\n",
                 aInfo.m_PixmapWidth, aInfo.m_PixmapHeight );
        fprintf( aInfo.m_Outfile, "$MODULE %s\n", CmpName );
        fprintf( aInfo.m_Outfile, "Po 0 0 0 15 00000000 00000000 ~~\n");
        fprintf( aInfo.m_Outfile, "T0 0 %d %d %d 0 %d N I %d \"G***\"\n",
                Ypos, fieldSize, fieldSize, fieldSize/5, FIELD_LAYER );
        fprintf( aInfo.m_Outfile, "T1 0 %d %d %d 0 %d N I %d \"%s\"\n",
                -Ypos, fieldSize, fieldSize, fieldSize/5, FIELD_LAYER, CmpName );
        break;

    case EESCHEMA_FMT:
        fprintf( aInfo.m_Outfile, "EESchema-LIBRARY Version 2.3\n" );
        fprintf( aInfo.m_Outfile, "#\n# %s\n", CmpName );
        fprintf( aInfo.m_Outfile, "# pixmap size w = %d, h = %d\n#\n",
                 aInfo.m_PixmapWidth, aInfo.m_PixmapHeight );

        // print reference and value
        fieldSize = 60;             // fields text size = 60 mils
        Ypos += fieldSize / 2;
        fprintf( aInfo.m_Outfile, "DEF %s G 0 40 Y Y 1 F N\n", CmpName );
        fprintf( aInfo.m_Outfile, "F0 \"#G\" 0 %d %d H I C CNN\n", Ypos, fieldSize );
        fprintf( aInfo.m_Outfile, "F1 \"%s\" 0 %d %d H I C CNN\n", CmpName, -Ypos, fieldSize );
        fprintf( aInfo.m_Outfile, "DRAW\n" );
        break;
    }
}


static void OuputEnd( BITMAPCONV_INFO& aInfo )
{
    switch( aInfo.m_Format )
    {
    case POSTSCRIPT_FMT:
        fprintf( aInfo.m_Outfile, "grestore\n" );
        fprintf( aInfo.m_Outfile, "%%EOF\n" );
        break;

    case PCBNEW_FMT:
        fprintf( aInfo.m_Outfile, "$EndMODULE %s\n", CmpName );
        fprintf( aInfo.m_Outfile, "$EndLIBRARY\n" );
        break;

    case EESCHEMA_FMT:
        fprintf( aInfo.m_Outfile, "ENDDRAW\n" );
        fprintf( aInfo.m_Outfile, "ENDDEF\n" );
        break;
    }
}


static void OuputOnePolygon( BITMAPCONV_INFO&                aInfo,
                             std::vector <potrace_dpoint_t>& aPolygonBuffer )
{
    unsigned ii;

    double   offsetX = aInfo.m_PixmapWidth / 2 * aInfo.m_ScaleX;
    double   offsetY = aInfo.m_PixmapHeight / 2 * aInfo.m_ScaleY;

    switch( aInfo.m_Format )
    {
    case POSTSCRIPT_FMT:
        fprintf( aInfo.m_Outfile, "%f %f moveto\n",
                 aPolygonBuffer[0].x * aInfo.m_ScaleX,
                 aPolygonBuffer[0].y * aInfo.m_ScaleY );
        for( ii = 1; ii < aPolygonBuffer.size(); ii++ )
            fprintf( aInfo.m_Outfile, "%f %f lineto\n",
                     aPolygonBuffer[ii].x * aInfo.m_ScaleX,
                     aPolygonBuffer[ii].y * aInfo.m_ScaleY );

        fprintf( aInfo.m_Outfile, "0 setgray fill\n" );
        break;

    case PCBNEW_FMT:
    {
        #define SILKSCREEN_N_FRONT 21
        int layer = SILKSCREEN_N_FRONT;
        int width = 1;
        fprintf( aInfo.m_Outfile, "DP %d %d %d %d %d %d %d\n",
                       0, 0, 0, 0,
                       aPolygonBuffer.size()+1,
                       width, layer );

        for( ii = 0; ii < aPolygonBuffer.size();  ii++ )
            fprintf( aInfo.m_Outfile, "Dl %d %d\n",
                    (int) ( aPolygonBuffer[ii].x * aInfo.m_ScaleX - offsetX ),
                    (int) ( aPolygonBuffer[ii].y * aInfo.m_ScaleY - offsetY ) );
        // Close polygon
        fprintf( aInfo.m_Outfile, "Dl %d %d\n",
                (int) ( aPolygonBuffer[0].x * aInfo.m_ScaleX - offsetX ),
                (int) ( aPolygonBuffer[0].y * aInfo.m_ScaleY - offsetY ) );
    }
        break;

    case EESCHEMA_FMT:
        fprintf( aInfo.m_Outfile, "P %d 0 0 1", aPolygonBuffer.size()+1 );
        for( ii = 0; ii < aPolygonBuffer.size(); ii++ )
            fprintf( aInfo.m_Outfile, " %d %d",
                    (int) ( aPolygonBuffer[ii].x * aInfo.m_ScaleX - offsetX ),
                    (int) ( aPolygonBuffer[ii].y * aInfo.m_ScaleY - offsetY ) );
       // Close polygon
        fprintf( aInfo.m_Outfile, " %d %d",
                (int) ( aPolygonBuffer[0].x * aInfo.m_ScaleX - offsetX ),
                (int) ( aPolygonBuffer[0].y * aInfo.m_ScaleY - offsetY ) );

        fprintf( aInfo.m_Outfile, " F\n" );
        break;
    }
}


static void CreateOutputFile( BITMAPCONV_INFO& aInfo )
{
    unsigned int i, n;
    int*         tag;

    std::vector <potrace_dpoint_t> cornersBuffer;

    potrace_dpoint_t( *c )[3];
    OuputHeader( aInfo );

    bool         main_outline = true;
    Bool_Engine* booleng = NULL;

    /* draw each as a polygon with no hole.
     * Bezier curves are approximated by a polyline
     */
    potrace_path_t* paths = aInfo.m_Paths;    // the list of paths
    while( paths != NULL )
    {
        n   = paths->curve.n;
        tag = paths->curve.tag;
        c   = paths->curve.c;
        potrace_dpoint_t startpoint = c[n - 1][2];
        cornersBuffer.push_back( startpoint );
        if( booleng == NULL )
        {
            booleng = new Bool_Engine();
            ArmBoolEng( booleng, true );
        }
        for( i = 0; i < n; i++ )
        {
            switch( tag[i] )
            {
            case POTRACE_CORNER:
                cornersBuffer.push_back( c[i][1] );
                cornersBuffer.push_back( c[i][2] );
                startpoint = c[i][2];
                break;

            case POTRACE_CURVETO:
                BezierToPolyline( cornersBuffer, startpoint, c[i][0], c[i][1], c[i][2] );
                startpoint = c[i][2];
                break;
            }
        }

        // Store current path
        if( main_outline )
        {
            main_outline = false;
            booleng->StartPolygonAdd( GROUP_A );
            for( i = 1; i < cornersBuffer.size(); i++ )
                booleng->AddPoint( cornersBuffer[i].x, cornersBuffer[i].y );

            booleng->EndPolygonAdd();
        }
        else
        {
            booleng->StartPolygonAdd( GROUP_B );
            for( i = 1; i < cornersBuffer.size(); i++ )
                booleng->AddPoint( cornersBuffer[i].x, cornersBuffer[i].y );

            booleng->EndPolygonAdd();
        }
        cornersBuffer.clear();

        /* at the end of a group of a positive path and its negative
         *  children, fill. */
        if( paths->next == NULL || paths->next->sign == '+' )
        {
            booleng->Do_Operation( BOOL_A_SUB_B );
            std::vector <potrace_dpoint_t> PolygonBuffer;
            while( booleng->StartPolygonGet() )
            {
                potrace_dpoint_t corner;
                PolygonBuffer.clear();
                while( booleng->PolygonHasMorePoints() )
                {
                    corner.x = booleng->GetPolygonXPoint();
                    corner.y = booleng->GetPolygonYPoint();
                    PolygonBuffer.push_back( corner );
                }

                booleng->EndPolygonGet();
                OuputOnePolygon( aInfo, PolygonBuffer );
                PolygonBuffer.clear();
            }

            delete booleng;
            booleng = NULL;
            main_outline = true;
        }
        paths = paths->next;
    }

    OuputEnd( aInfo );
}


/* render a Bezier curve. */
void BezierToPolyline( std::vector <potrace_dpoint_t>& aCornersBuffer,
                       potrace_dpoint_t                p1,
                       potrace_dpoint_t                p2,
                       potrace_dpoint_t                p3,
                       potrace_dpoint_t                p4 )
{
    double dd0, dd1, dd, delta, e2, epsilon, t;

    // p1 = starting point

    /* we approximate the curve by small line segments. The interval
     *  size, epsilon, is determined on the fly so that the distance
     *  between the true curve and its approximation does not exceed the
     *  desired accuracy delta. */

    delta = 0.5; /* desired accuracy, in pixels */

    /* let dd = maximal value of 2nd derivative over curve - this must
     *  occur at an endpoint. */
    dd0     = sq( p1.x - 2 * p2.x + p3.x ) + sq( p1.y - 2 * p2.y + p3.y );
    dd1     = sq( p2.x - 2 * p3.x + p4.x ) + sq( p2.y - 2 * p3.y + p4.y );
    dd      = 6 * sqrt( max( dd0, dd1 ) );
    e2      = 8 * delta <= dd ? 8 * delta / dd : 1;
    epsilon = sqrt( e2 ); /* necessary interval size */

    for( t = epsilon; t<1; t += epsilon )
    {
        potrace_dpoint_t intermediate_point;
        intermediate_point.x = p1.x * cu( 1 - t ) +
                               3* p2.x* sq( 1 - t ) * t +
                               3 * p3.x * (1 - t) * sq( t ) +
                               p4.x*    cu( t );

        intermediate_point.y = p1.y * cu( 1 - t ) +
                               3* p2.y* sq( 1 - t ) * t +
                               3 * p3.y * (1 - t) * sq( t ) + p4.y* cu( t );

        aCornersBuffer.push_back( intermediate_point );
    }

    aCornersBuffer.push_back( p4 );
}
+5 −5
Original line number Diff line number Diff line
@@ -676,7 +676,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum,
    {
        aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
                          *aLineNum );
        while( GetLine( aFile, aLine, aLineNum, 1024 ) )
        while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
        {
            p = strtok( aLine, " \t\n" );
            if( stricmp( p, "ENDDEF" ) == 0 )
@@ -726,7 +726,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum,
        m_options = ENTRY_POWER;

    /* Read next lines */
    while( GetLine( aFile, aLine, aLineNum, 1024 ) )
    while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
    {
        p = strtok( aLine, " \t\n" );

@@ -775,7 +775,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,

    while( true )
    {
        if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL )
        if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
        {
            aErrorMsg = wxT( "file ended prematurely loading component draw element" );
            return false;
@@ -830,7 +830,7 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,
            /* Flush till end of draw section */
            do
            {
                if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL )
                if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
                {
                    aErrorMsg = wxT( "file ended prematurely while attempting \
to flush to end of drawing section." );
@@ -899,7 +899,7 @@ bool LIB_COMPONENT::LoadFootprints( FILE* aFile, char* aLine,
{
    while( true )
    {
        if( GetLine( aFile, aLine, aLineNum, 1024 ) == NULL )
        if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
        {
            aErrorMsg = wxT( "file ended prematurely while loading footprints" );
            return false;
Loading