~cern-kicad/kicad/kicad-pns-tom

« back to all changes in this revision

Viewing changes to common/title_block_shapes.cpp

  • Committer: Maciej Suminski
  • Date: 2013-08-02 13:57:24 UTC
  • mfrom: (4024.1.238 kicad)
  • mto: This revision was merged to the branch mainline in revision 4221.
  • Revision ID: maciej.suminski@cern.ch-20130802135724-gix6orezshkukodv
Upstream merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * @file title_block_shape.cpp
3
 
 * @brief description of graphic items and texts to build a title block
4
 
 */
5
 
 
6
 
/*
7
 
 * This program source code file is part of KiCad, a free EDA CAD application.
8
 
 *
9
 
 * Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
10
 
 * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors.
11
 
 *
12
 
 *
13
 
 * This program is free software; you can redistribute it and/or
14
 
 * modify it under the terms of the GNU General Public License
15
 
 * as published by the Free Software Foundation; either version 2
16
 
 * of the License, or (at your option) any later version.
17
 
 *
18
 
 * This program is distributed in the hope that it will be useful,
19
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 
 * GNU General Public License for more details.
22
 
 *
23
 
 * You should have received a copy of the GNU General Public License
24
 
 * along with this program; if not, you may find one here:
25
 
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26
 
 * or you may search the http://www.gnu.org website for the version 2 license,
27
 
 * or you may write to the Free Software Foundation, Inc.,
28
 
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
29
 
 */
30
 
 
31
 
 
32
 
/*
33
 
 * the class WORKSHEET_DATAITEM (and WORKSHEET_DATAITEM_TEXT) defines
34
 
 * a basic shape of a page layout ( frame references and title block )
35
 
 * Basic shapes are line, rect and texts
36
 
 * the WORKSHEET_DATAITEM coordinates units is the mm, and are relative to
37
 
 * one of 4 page corners.
38
 
 *
39
 
 * These items cannot be drawn or plot "as this". they should be converted
40
 
 * to a "draw list" (WS_DRAW_ITEM_BASE and derived items)
41
 
 
42
 
 * The list of these items is stored in a WORKSHEET_LAYOUT instance.
43
 
 *
44
 
 * When building the draw list:
45
 
 * the WORKSHEET_LAYOUT is used to create a WS_DRAW_ITEM_LIST
46
 
 *  coordinates are converted to draw/plot coordinates.
47
 
 *  texts are expanded if they contain format symbols.
48
 
 *  Items with m_RepeatCount > 1 are created m_RepeatCount times
49
 
 *
50
 
 * the WORKSHEET_LAYOUT is created only once.
51
 
 * the WS_DRAW_ITEM_LIST is created each time the page layout is plot/drawn
52
 
 *
53
 
 * the WORKSHEET_LAYOUT instance is created from a S expression which
54
 
 * describes the page layout (can be the default page layout or a custom file).
55
 
 */
56
 
 
57
 
#include <fctsys.h>
58
 
#include <drawtxt.h>
59
 
#include <worksheet.h>
60
 
#include <class_title_block.h>
61
 
#include <worksheet_shape_builder.h>
62
 
 
63
 
WORKSHEET_DATAITEM_POLYPOLYGON::WORKSHEET_DATAITEM_POLYPOLYGON() :
64
 
    WORKSHEET_DATAITEM( WS_POLYPOLYGON )
65
 
{
66
 
    m_Orient = 0.0;
67
 
}
68
 
 
69
 
const DPOINT WORKSHEET_DATAITEM_POLYPOLYGON::GetCornerPosition( unsigned aIdx,
70
 
                                                         int aRepeat ) const
71
 
{
72
 
    DPOINT pos = m_Corners[aIdx];
73
 
 
74
 
    // Rotation:
75
 
    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
76
 
    pos += GetStartPos( aRepeat );
77
 
    return pos;
78
 
}
79
 
 
80
 
void WORKSHEET_DATAITEM_POLYPOLYGON::SetBoundingBox()
81
 
{
82
 
    if( m_Corners.size() == 0 )
83
 
    {
84
 
        m_minCoord.x = m_maxCoord.x = 0.0;
85
 
        m_minCoord.y = m_maxCoord.y = 0.0;
86
 
        return;
87
 
    }
88
 
 
89
 
    DPOINT pos;
90
 
    pos = m_Corners[0];
91
 
    RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
92
 
    m_minCoord = m_maxCoord = pos;
93
 
 
94
 
    for( unsigned ii = 1; ii < m_Corners.size(); ii++ )
95
 
    {
96
 
        pos = m_Corners[ii];
97
 
        RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
98
 
 
99
 
        if( m_minCoord.x > pos.x )
100
 
            m_minCoord.x = pos.x;
101
 
 
102
 
        if( m_minCoord.y > pos.y )
103
 
            m_minCoord.y = pos.y;
104
 
 
105
 
        if( m_maxCoord.x < pos.x )
106
 
            m_maxCoord.x = pos.x;
107
 
 
108
 
        if( m_maxCoord.y < pos.y )
109
 
            m_maxCoord.y = pos.y;
110
 
    }
111
 
}
112
 
 
113
 
bool WORKSHEET_DATAITEM_POLYPOLYGON::IsInsidePage( int ii ) const
114
 
{
115
 
    DPOINT pos = GetStartPos( ii );
116
 
    pos += m_minCoord;  // left top pos of bounding box
117
 
 
118
 
    if( m_LT_Corner.x > pos.x || m_LT_Corner.y > pos.y )
119
 
        return false;
120
 
 
121
 
    pos = GetStartPos( ii );
122
 
    pos += m_maxCoord;  // rignt bottom pos of bounding box
123
 
 
124
 
    if( m_RB_Corner.x < pos.x || m_RB_Corner.y < pos.y )
125
 
        return false;
126
 
 
127
 
    return true;
128
 
}
129
 
 
130
 
const wxPoint WORKSHEET_DATAITEM_POLYPOLYGON::GetCornerPositionUi( unsigned aIdx,
131
 
                                                            int aRepeat ) const
132
 
{
133
 
    DPOINT pos = GetCornerPosition( aIdx, aRepeat );
134
 
    pos = pos * m_WSunits2Iu;
135
 
    return wxPoint( int(pos.x), int(pos.y) );
136
 
}
137
 
 
138
 
WORKSHEET_DATAITEM_TEXT::WORKSHEET_DATAITEM_TEXT( const wxChar* aTextBase ) :
139
 
    WORKSHEET_DATAITEM( WS_TEXT )
140
 
{
141
 
    m_TextBase = aTextBase;
142
 
    m_IncrementLabel = 1;
143
 
    m_Hjustify = GR_TEXT_HJUSTIFY_LEFT;
144
 
    m_Vjustify = GR_TEXT_VJUSTIFY_CENTER;
145
 
    m_Orient = 0.0;
146
 
    m_TextSize.x = m_TextSize.y = TB_DEFAULT_TEXTSIZE;
147
 
}
148
 
 
149
 
void WORKSHEET_DATAITEM_TEXT::TransfertSetupToGraphicText( WS_DRAW_ITEM_TEXT* aGText )
150
 
{
151
 
    aGText->SetHorizJustify( m_Hjustify ) ;
152
 
    aGText->SetVertJustify( m_Vjustify );
153
 
    aGText->SetOrientation( m_Orient * 10 );    // graphic text orient unit = 0.1 degree
154
 
}
155
 
 
156
 
void WORKSHEET_DATAITEM_TEXT::IncrementLabel( int aIncr )
157
 
{
158
 
    wxChar lbchar = m_TextBase[0];
159
 
    if( lbchar >= '0' &&  lbchar <= '9' )
160
 
        // A number is expected:
161
 
        m_FullText.Printf( wxT("%d"), aIncr + lbchar - '0' );
162
 
    else
163
 
        m_FullText.Printf( wxT("%c"), aIncr + lbchar );
164
 
}
165
 
 
166
 
void WORKSHEET_DATAITEM_TEXT::SetConstrainedTextSize()
167
 
{
168
 
    m_ConstrainedTextSize = m_TextSize;
169
 
 
170
 
    if( m_BoundingBoxSize.x )
171
 
    {
172
 
        bool italic = (m_Flags & USE_ITALIC) != 0;
173
 
        int linewidth = 0;
174
 
        int lenMsg   = ReturnGraphicTextWidth( m_FullText, m_TextSize.x, italic, linewidth );
175
 
        if( lenMsg > m_BoundingBoxSize.x )
176
 
            m_ConstrainedTextSize.x = m_TextSize.x * m_BoundingBoxSize.x / lenMsg;
177
 
    }
178
 
 
179
 
    if( m_BoundingBoxSize.y )
180
 
    {
181
 
        if( m_ConstrainedTextSize.y > m_BoundingBoxSize.y )
182
 
            m_ConstrainedTextSize.y = m_BoundingBoxSize.y;
183
 
    }
184
 
}
185
 
 
186
 
const DPOINT WORKSHEET_DATAITEM::GetStartPos( int ii ) const
187
 
{
188
 
    DPOINT pos;
189
 
    pos.x = m_Pos.m_Pos.x + ( m_IncrementVector.x * ii );
190
 
    pos.y = m_Pos.m_Pos.y + ( m_IncrementVector.y * ii );
191
 
 
192
 
    switch( m_Pos.m_Anchor )
193
 
    {
194
 
        case RB_CORNER:      // right bottom corner
195
 
            pos = m_RB_Corner - pos;
196
 
            break;
197
 
 
198
 
        case RT_CORNER:      // right top corner
199
 
            pos.x = m_RB_Corner.x - pos.x;
200
 
            pos.y = m_LT_Corner.y + pos.y;
201
 
            break;
202
 
 
203
 
        case LB_CORNER:      // left bottom corner
204
 
            pos.x = m_LT_Corner.x + pos.x;
205
 
            pos.y = m_RB_Corner.y - pos.y;
206
 
            break;
207
 
 
208
 
        case LT_CORNER:      // left top corner
209
 
            pos = m_LT_Corner + pos;
210
 
            break;
211
 
    }
212
 
 
213
 
    return pos;
214
 
}
215
 
 
216
 
const wxPoint WORKSHEET_DATAITEM::GetStartPosUi( int ii ) const
217
 
{
218
 
    DPOINT pos = GetStartPos( ii );
219
 
    pos = pos * m_WSunits2Iu;
220
 
    return wxPoint( int(pos.x), int(pos.y) );
221
 
}
222
 
 
223
 
const DPOINT WORKSHEET_DATAITEM::GetEndPos( int ii ) const
224
 
{
225
 
    DPOINT pos;
226
 
    pos.x = m_End.m_Pos.x + ( m_IncrementVector.x * ii );
227
 
    pos.y = m_End.m_Pos.y + ( m_IncrementVector.y * ii );
228
 
    switch( m_End.m_Anchor )
229
 
    {
230
 
        case RB_CORNER:      // right bottom corner
231
 
            pos = m_RB_Corner - pos;
232
 
            break;
233
 
 
234
 
        case RT_CORNER:      // right top corner
235
 
            pos.x = m_RB_Corner.x - pos.x;
236
 
            pos.y = m_LT_Corner.y + pos.y;
237
 
            break;
238
 
 
239
 
        case LB_CORNER:      // left bottom corner
240
 
            pos.x = m_LT_Corner.x + pos.x;
241
 
            pos.y = m_RB_Corner.y - pos.y;
242
 
            break;
243
 
 
244
 
        case LT_CORNER:      // left top corner
245
 
            pos = m_LT_Corner + pos;
246
 
            break;
247
 
    }
248
 
 
249
 
    return pos;
250
 
}
251
 
 
252
 
const wxPoint WORKSHEET_DATAITEM::GetEndPosUi( int ii ) const
253
 
{
254
 
    DPOINT pos = GetEndPos( ii );
255
 
    pos = pos * m_WSunits2Iu;
256
 
    return wxPoint( int(pos.x), int(pos.y) );
257
 
}
258
 
 
259
 
 
260
 
bool WORKSHEET_DATAITEM::IsInsidePage( int ii ) const
261
 
{
262
 
    DPOINT pos = GetStartPos( ii );
263
 
 
264
 
    if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x )
265
 
        return false;
266
 
 
267
 
    if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y )
268
 
        return false;
269
 
 
270
 
    pos = GetEndPos( ii );
271
 
 
272
 
    if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x )
273
 
        return false;
274
 
 
275
 
    if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y )
276
 
        return false;
277
 
 
278
 
    return true;
279
 
}
280
 
 
281
 
double WORKSHEET_DATAITEM::m_WSunits2Iu = 1.0;
282
 
DPOINT WORKSHEET_DATAITEM::m_RB_Corner;
283
 
DPOINT WORKSHEET_DATAITEM::m_LT_Corner;
284
 
 
285
 
WORKSHEET_LAYOUT dataList;  // The layout shape
286
 
 
287
 
void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
288
 
                       const wxString& aPaperFormat,
289
 
                       const wxString& aFileName,
290
 
                       const wxString& aSheetPathHumanReadable,
291
 
                       const TITLE_BLOCK& aTitleBlock,
292
 
                       EDA_COLOR_T aLineColor, EDA_COLOR_T aTextColor )
293
 
{
294
 
    #define milsTomm (25.4/1000)
295
 
 
296
 
    m_titleBlock = &aTitleBlock,
297
 
    m_paperFormat = &aPaperFormat,
298
 
    m_fileName = &aFileName,
299
 
    m_sheetFullName = &aSheetPathHumanReadable;
300
 
 
301
 
    // Build the basic layout shape, if the layout list is empty
302
 
    if( dataList.GetCount() == 0 )
303
 
        dataList.SetLayout();
304
 
 
305
 
    WORKSHEET_DATAITEM::m_WSunits2Iu = m_milsToIu / milsTomm;
306
 
 
307
 
    // Left top corner position
308
 
    DPOINT lt_corner;
309
 
    lt_corner.x = m_LTmargin.x;
310
 
    lt_corner.y = m_LTmargin.y;
311
 
    WORKSHEET_DATAITEM::m_LT_Corner = lt_corner * milsTomm;
312
 
 
313
 
    // Right bottom corner position
314
 
    DPOINT rb_corner;
315
 
    rb_corner.x = m_pageSize.x - m_RBmargin.x;
316
 
    rb_corner.y = m_pageSize.y - m_RBmargin.y;
317
 
    WORKSHEET_DATAITEM::m_RB_Corner = rb_corner * milsTomm;
318
 
 
319
 
    WS_DRAW_ITEM_TEXT* gtext;
320
 
    int pensize;
321
 
    EDA_COLOR_T color;
322
 
 
323
 
    for( unsigned ii = 0; ; ii++ )
324
 
    {
325
 
        WORKSHEET_DATAITEM*  wsItem = dataList.GetItem( ii );
326
 
 
327
 
        if( wsItem == NULL )
328
 
            break;
329
 
 
330
 
        pensize = wsItem->GetPenSizeUi();
331
 
 
332
 
        switch( wsItem->m_Type )
333
 
        {
334
 
        case WORKSHEET_DATAITEM::WS_TEXT:
335
 
        {
336
 
            WORKSHEET_DATAITEM_TEXT * wsText = (WORKSHEET_DATAITEM_TEXT*)wsItem;
337
 
            wsText->m_FullText = BuildFullText( wsText->m_TextBase );
338
 
            if( wsText->m_FullText.IsEmpty() )
339
 
                break;
340
 
 
341
 
            if( pensize == 0 )
342
 
                pensize = m_penSize;
343
 
 
344
 
            color = aLineColor;
345
 
 
346
 
            if( wsText->m_Flags & USE_TEXT_COLOR )
347
 
                color = aTextColor;
348
 
 
349
 
            wsText->SetConstrainedTextSize();
350
 
            wxSize textsize;
351
 
 
352
 
            textsize.x = KiROUND( wsText->m_ConstrainedTextSize.x
353
 
                                  * WORKSHEET_DATAITEM::m_WSunits2Iu );
354
 
            textsize.y = KiROUND( wsText->m_ConstrainedTextSize.y
355
 
                                  * WORKSHEET_DATAITEM::m_WSunits2Iu );
356
 
 
357
 
            if( wsText->IsBold())
358
 
                pensize = GetPenSizeForBold( std::min( textsize.x, textsize.y ) );
359
 
 
360
 
            for( int jj = 0; jj < wsText->m_RepeatCount; jj++)
361
 
            {
362
 
                if( ! wsText->IsInsidePage( jj ) )
363
 
                    continue;
364
 
 
365
 
                Append( gtext = new WS_DRAW_ITEM_TEXT( wsText->m_FullText,
366
 
                                                       wsText->GetStartPosUi( jj ),
367
 
                                                       textsize,
368
 
                                                       pensize, color,
369
 
                                                       wsText->IsItalic(),
370
 
                                                       wsText->IsBold() ) );
371
 
                wsText->TransfertSetupToGraphicText( gtext );
372
 
 
373
 
                // Increment label for the next text
374
 
                if( wsText->m_RepeatCount > 1 )
375
 
                    wsText->IncrementLabel( jj+1 );
376
 
            }
377
 
        }
378
 
            break;
379
 
 
380
 
        case WORKSHEET_DATAITEM::WS_SEGMENT:
381
 
            if( pensize == 0 )
382
 
                pensize = m_penSize;
383
 
 
384
 
            for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ )
385
 
            {
386
 
                if( ! wsItem->IsInsidePage( jj ) )
387
 
                    continue;
388
 
                Append( new WS_DRAW_ITEM_LINE( wsItem->GetStartPosUi( jj ),
389
 
                                               wsItem->GetEndPosUi( jj ),
390
 
                                               pensize, aLineColor ) );
391
 
            }
392
 
            break;
393
 
 
394
 
        case WORKSHEET_DATAITEM::WS_RECT:
395
 
            if( pensize == 0 )
396
 
                pensize = m_penSize;
397
 
 
398
 
            for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ )
399
 
            {
400
 
                if( ! wsItem->IsInsidePage( jj ) )
401
 
                    break;
402
 
 
403
 
                Append( new WS_DRAW_ITEM_RECT( wsItem->GetStartPosUi( jj ),
404
 
                                               wsItem->GetEndPosUi( jj ),
405
 
                                               pensize, aLineColor ) );
406
 
            }
407
 
            break;
408
 
 
409
 
        case WORKSHEET_DATAITEM::WS_POLYPOLYGON:
410
 
        {
411
 
            WORKSHEET_DATAITEM_POLYPOLYGON * wspoly =
412
 
                (WORKSHEET_DATAITEM_POLYPOLYGON*) wsItem;
413
 
            for( int jj = 0; jj < wsItem->m_RepeatCount; jj++ )
414
 
            {
415
 
                if( ! wsItem->IsInsidePage( jj ) )
416
 
                    continue;
417
 
 
418
 
                for( int kk = 0; kk < wspoly->GetPolyCount(); kk++ )
419
 
                {
420
 
                    const bool fill = true;
421
 
                    WS_DRAW_ITEM_POLYGON* poly = new WS_DRAW_ITEM_POLYGON( fill,
422
 
                                                   pensize, aLineColor );
423
 
                    Append( poly );
424
 
 
425
 
                    // Create polygon outline
426
 
                    unsigned ist = wspoly->GetPolyIndexStart( kk );
427
 
                    unsigned iend = wspoly->GetPolyIndexEnd( kk );
428
 
                    while( ist <= iend )
429
 
                        poly->m_Corners.push_back(
430
 
                            wspoly->GetCornerPositionUi( ist++, jj ) );
431
 
 
432
 
                }
433
 
            }
434
 
        }
435
 
            break;
436
 
        }
437
 
    }
438
 
}