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

Custom page layout: add support for poly-polygons (useful for logos)

parent 98eb5e75
Loading
Loading
Loading
Loading
+58 −33
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
 *  pos
 *  start
 *  end
 *  pts
 *  xy
 *  maxlen
 *  maxheight
 *  font
@@ -123,6 +125,29 @@
 * example:
 * (tbtext \"Size: %Z\" ...) displays "Size A4" or Size USLetter"
 *
 *  Poly Polygons
 *  Set of filled polygons are supported.
 *
 *  The main purpose is to allow logos, or complex shapes
 *  They support the repeat and rotation options
 *  They are defined by
 *  (polygon (position ..) <rotation>  <linewidth>
 *  the parameter linewidth defines the pen size used to draw/plot
 *  the polygon outlines (default = 0)
 *  example:
 *  (polygon (pos 134 18 rbcorner) (rotate 20)  (linewidth 0.00254)
 *
 *  and a list of corners like
 *  (pts (xy 20.574 8.382) (xy 19.9009 8.382) (xy 19.9009 6.26364) (xy 19.7485 5.98932)
 *  .... )
 *
 *  each sequence like
 *  (pts (xy 20.574 8.382) (xy 19.9009 8.382) (xy 19.9009 6.26364) (xy 19.7485 5.98932)
 *  .... )
 *  defines a polygon.
 *  Each coordinate is relative to the polygon position.
 *  Therefore a "polygon" is in fact a set of polygons, of a poly polygon
 *
 */

#include <worksheet.h>      // defaultPageLayout
+104 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ private:
    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 parsePolygon( WORKSHEET_DATAITEM_POLYPOLYGON * aItem )
        throw( IO_ERROR, PARSE_ERROR );
    void parsePolyOutline( WORKSHEET_DATAITEM_POLYPOLYGON * aItem )
        throw( IO_ERROR, PARSE_ERROR );
    void parseCoordinate( POINT_COORD& aCoord) throw( IO_ERROR, PARSE_ERROR );
};

@@ -127,6 +131,12 @@ void PAGE_LAYOUT_READER_PARSER::Parse( WORKSHEET_LAYOUT* aLayout )
            aLayout->Append( item );
            break;

        case T_polygon:
            item = new WORKSHEET_DATAITEM_POLYPOLYGON();
            parsePolygon(  (WORKSHEET_DATAITEM_POLYPOLYGON*) item );
            aLayout->Append( item );
            break;

        case T_tbtext:
            NeedSYMBOLorNUMBER();
            item = new WORKSHEET_DATAITEM_TEXT( FromUTF8() );
@@ -177,6 +187,100 @@ void PAGE_LAYOUT_READER_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR )
    }
}

void PAGE_LAYOUT_READER_PARSER::parsePolygon( WORKSHEET_DATAITEM_POLYPOLYGON * aItem )
    throw( IO_ERROR, PARSE_ERROR )
{
    aItem->m_LineWidth = 0;

    T token;

    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_pts:
            parsePolyOutline( aItem );
            aItem->CloseContour();
            break;

        case T_rotate:
            aItem->m_Orient = parseDouble();
            NeedRIGHT();
            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;
        }
    }

    aItem->SetBoundingBox();
}

void PAGE_LAYOUT_READER_PARSER::parsePolyOutline( WORKSHEET_DATAITEM_POLYPOLYGON * aItem )
    throw( IO_ERROR, PARSE_ERROR )
{
    DPOINT corner;
    T token;

    while( ( token = NextTok() ) != T_RIGHT )
    {
        if( token == T_EOF)
           break;

        if( token == T_LEFT )
            token = NextTok();

        switch( token )
        {
        case T_xy:
            corner.x = parseDouble();
            corner.y = parseDouble();
            aItem->AppendCorner( corner );
            NeedRIGHT();
            break;

        default:
            Unexpected( CurText() );
            break;
        }
    }
}

void PAGE_LAYOUT_READER_PARSER::parseGraphic( WORKSHEET_DATAITEM * aItem )
    throw( IO_ERROR, PARSE_ERROR )
{
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@ name
pos
start
end
pts
xy
maxlen
maxheight
font
+111 −12
Original line number Diff line number Diff line
@@ -60,6 +60,80 @@
#include <class_title_block.h>
#include <worksheet_shape_builder.h>

WORKSHEET_DATAITEM_POLYPOLYGON::WORKSHEET_DATAITEM_POLYPOLYGON() :
    WORKSHEET_DATAITEM( WS_POLYPOLYGON )
{
    m_Orient = 0.0;
}

const DPOINT WORKSHEET_DATAITEM_POLYPOLYGON::GetCornerPosition( unsigned aIdx,
                                                         int aRepeat ) const
{
    DPOINT pos = m_Corners[aIdx];

    // Rotation:
    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
    pos += GetStartPos( aRepeat );
    return pos;
}

void WORKSHEET_DATAITEM_POLYPOLYGON::SetBoundingBox()
{
    if( m_Corners.size() == 0 )
    {
        m_minCoord.x = m_maxCoord.x = 0.0;
        m_minCoord.y = m_maxCoord.y = 0.0;
        return;
    }

    DPOINT pos;
    pos = m_Corners[0];
    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
    m_minCoord = m_maxCoord = pos;

    for( unsigned ii = 1; ii < m_Corners.size(); ii++ )
    {
        pos = m_Corners[ii];
        RotatePoint( &pos.x, &pos.y, m_Orient * 10 );

        if( m_minCoord.x > pos.x )
            m_minCoord.x = pos.x;

        if( m_minCoord.y > pos.y )
            m_minCoord.y = pos.y;

        if( m_maxCoord.x < pos.x )
            m_maxCoord.x = pos.x;

        if( m_maxCoord.y < pos.y )
            m_maxCoord.y = pos.y;
    }
}

bool WORKSHEET_DATAITEM_POLYPOLYGON::IsInsidePage( int ii ) const
{
    DPOINT pos = GetStartPos( ii );
    pos += m_minCoord;  // left top pos of bounding box

    if( m_LT_Corner.x > pos.x || m_LT_Corner.y > pos.y )
        return false;

    pos = GetStartPos( ii );
    pos += m_maxCoord;  // rignt bottom pos of bounding box

    if( m_RB_Corner.x < pos.x || m_RB_Corner.y < pos.y )
        return false;

    return true;
}

const wxPoint WORKSHEET_DATAITEM_POLYPOLYGON::GetCornerPositionUi( unsigned aIdx,
                                                            int aRepeat ) const
{
    DPOINT pos = GetCornerPosition( aIdx, aRepeat );
    pos = pos * m_WSunits2Iu;
    return wxPoint( int(pos.x), int(pos.y) );
}

WORKSHEET_DATAITEM_TEXT::WORKSHEET_DATAITEM_TEXT( const wxChar* aTextBase ) :
    WORKSHEET_DATAITEM( WS_TEXT )
@@ -253,6 +327,8 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
        if( wsItem == NULL )
            break;

        pensize = wsItem->GetPenSizeUi();

        switch( wsItem->m_Type )
        {
        case WORKSHEET_DATAITEM::WS_TEXT:
@@ -262,8 +338,6 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
            if( wsText->m_FullText.IsEmpty() )
                break;

            pensize = wsText->GetPenSizeUi();

            if( pensize == 0 )
                pensize = m_penSize;

@@ -283,10 +357,11 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
            if( wsText->IsBold())
                pensize = GetPenSizeForBold( std::min( textsize.x, textsize.y ) );

            for( int jj = 0; jj < wsText->m_RepeatCount; )
            for( int jj = 0; jj < wsText->m_RepeatCount; jj++)
            {
                if( ! wsText->IsInsidePage( jj ) )
                    break;
                    continue;

                Append( gtext = new WS_DRAW_ITEM_TEXT( wsText->m_FullText,
                                                       wsText->GetStartPosUi( jj ),
                                                       textsize,
@@ -295,23 +370,21 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
                                                       wsText->IsBold() ) );
                wsText->TransfertSetupToGraphicText( gtext );

                jj++;
                if( wsText->m_RepeatCount > 1 )     // Try to increment label
                    wsText->IncrementLabel( jj );
                // Increment label for the next text
                if( wsText->m_RepeatCount > 1 )
                    wsText->IncrementLabel( jj+1 );
            }
        }
            break;

        case WORKSHEET_DATAITEM::WS_SEGMENT:
            pensize = wsItem->GetPenSizeUi();

            if( pensize == 0 )
                pensize = m_penSize;

            for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ )
            {
                if( ! wsItem->IsInsidePage( jj ) )
                    break;
                    continue;
                Append( new WS_DRAW_ITEM_LINE( wsItem->GetStartPosUi( jj ),
                                               wsItem->GetEndPosUi( jj ),
                                               pensize, aLineColor ) );
@@ -319,8 +392,6 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
            break;

        case WORKSHEET_DATAITEM::WS_RECT:
            pensize = wsItem->GetPenSizeUi();

            if( pensize == 0 )
                pensize = m_penSize;

@@ -334,6 +405,34 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
                                               pensize, aLineColor ) );
            }
            break;

        case WORKSHEET_DATAITEM::WS_POLYPOLYGON:
        {
            WORKSHEET_DATAITEM_POLYPOLYGON * wspoly =
                (WORKSHEET_DATAITEM_POLYPOLYGON*) wsItem;
            for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ )
            {
                if( ! wsItem->IsInsidePage( jj ) )
                    continue;

                for( int kk = 0; kk < wspoly->GetPolyCount(); kk++ )
                {
                    const bool fill = true;
                    WS_DRAW_ITEM_POLYGON* poly = new WS_DRAW_ITEM_POLYGON( fill,
                                                   pensize, aLineColor );
                    Append( poly );

                    // Create polygon outline
                    unsigned ist = wspoly->GetPolyIndexStart( kk );
                    unsigned iend = wspoly->GetPolyIndexEnd( kk );
                    while( ist <= iend )
                        poly->m_Corners.push_back(
                            wspoly->GetCornerPositionUi( ist++, jj ) );

                }
            }
        }
            break;
        }
    }
}
+96 −2
Original line number Diff line number Diff line
@@ -52,13 +52,20 @@ public:


// Work sheet structure type definitions.
// Basic items are:
// * segment and rect (defined by 2 points)
// * text (defined by a coordinate), the text and its justifications
// * poly polygon defined by a coordinate, and a set of list of corners
//   ( because we use it for logos, there are more than one polygon
//   in this description
class WORKSHEET_DATAITEM
{
public:
    enum WS_ItemType {
        WS_TEXT,
        WS_SEGMENT,
        WS_RECT
        WS_RECT,
        WS_POLYPOLYGON
    };
    WS_ItemType       m_Type;
    POINT_COORD       m_Pos;
@@ -87,6 +94,8 @@ public:
        m_LineWidth = 0.0;
    }

    virtual ~WORKSHEET_DATAITEM() {}

    void SetStart( double aPosx, double aPosy, enum corner_anchor aAnchor = RB_CORNER )
    {
        m_Pos.m_Pos.x = aPosx;
@@ -105,8 +114,92 @@ public:
    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 ); }

    /**
     * @return true if the item is inside the rectangle defined by the
     * 4 corners, false otherwise.
     */
    virtual bool IsInsidePage( int ii ) const;
};

class WORKSHEET_DATAITEM_POLYPOLYGON : public WORKSHEET_DATAITEM
{
public:
    double            m_Orient;             //  Orientation in degrees
    std::vector<DPOINT> m_Corners;          // corner list

private:
    std::vector<unsigned> m_polyIndexEnd;   // index of the last point of each polygon
    DPOINT            m_minCoord;           // min coord of corners, relative to m_Pos
    DPOINT            m_maxCoord;           // max coord of corners, relative to m_Pos

public:
    WORKSHEET_DATAITEM_POLYPOLYGON( );

    /**
     * add a corner in corner list
     * @param aCorner: the item to append
     */
    void AppendCorner( const DPOINT& aCorner )
    {
        m_Corners.push_back( aCorner );
    }

    /**
     * Closes the current contour, by storing the index of the last corner
     * of the current polygon in m_polyIndexEnd.
     */
    void CloseContour()
    {
        m_polyIndexEnd.push_back( m_Corners.size() -1 );
    }

    /**
     * @return the count of contours in the poly polygon
     */
    int GetPolyCount() const { return (int) m_polyIndexEnd.size(); }

    /**
     * @return the index of the first corner of the contour aCountour
     * @param aContour = the index of the contour
     */
    unsigned GetPolyIndexStart( unsigned aContour) const
    {
        if( aContour == 0 )
            return 0;
        else
            return m_polyIndexEnd[aContour-1] + 1;
    }

    /**
     * @return the index of the last corner of the contour aCountour
     * @param aContour = the index of the contour
     */
    unsigned GetPolyIndexEnd( unsigned aContour) const
    {
        return m_polyIndexEnd[aContour];
    }

    /**
     * @return the coordinate (in mm) of the corner aIdx,
     * for the repeated item aRepeat
     */
    const DPOINT GetCornerPosition( unsigned aIdx, int aRepeat = 0 ) const;

    /**
     * @return the coordinate (in draw/plot units) of the corner aIdx,
     * for the repeated item aRepeat
     */
    const wxPoint GetCornerPositionUi( unsigned aIdx, int aRepeat = 0 ) const;

    /**
     * calculate the bounding box of the set  polygons
     */
    void SetBoundingBox();


    bool IsInsidePage( int ii ) const;
};

class WORKSHEET_DATAITEM_TEXT : public WORKSHEET_DATAITEM
@@ -233,6 +326,7 @@ class WS_DRAW_ITEM_POLYGON : public WS_DRAW_ITEM_BASE

public:
    std::vector <wxPoint> m_Corners;

public:
    WS_DRAW_ITEM_POLYGON( bool aFill, int aPenWidth, EDA_COLOR_T aColor ) :
        WS_DRAW_ITEM_BASE( wsg_poly, aColor )
Loading