wxArt2D
gdsio.cpp
Go to the documentation of this file.
1 /*! \file gdsio/src/gdsio.cpp
2  \brief GdsII parser
3  \author Probably Klaas Holwerda
4 
5  Copyright: 2001-2004 (C) Probably Klaas Holwerda
6 
7  Licence: wxWidgets Licence
8 
9  RCS-ID: $Id: gdsio.cpp,v 1.135 2009/06/07 13:28:08 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21 
22 #include <cstring>
23 
24 #ifdef new
25 #undef new
26 #endif
27 
28 #include "a2dprivate.h"
29 
30 #if wxART2D_USE_GDSIO
31 
32 #include "wx/docview/doccom.h"
33 #include "wx/canvas/candefs.h"
34 #include "wx/canvas/canglob.h"
35 #include "wx/canvas/algos.h"
36 #include "wx/editor/candoc.h"
37 #include "wx/canvas/canobj.h"
38 #include "wx/canvas/vpath.h"
39 #include "wx/canvas/layerinf.h"
40 #include "wx/canvas/recur.h"
41 #include "wx/canvas/drawer.h"
42 #include "wx/canvas/cameleon.h"
43 #include "wx/gdsio/gdsio.h"
44 #include "wx/gdsio/gdserr.h"
45 
46 #include <wx/datetime.h>
47 #include <limits.h>
48 
49 const a2dError a2dError_GDSIIparse( wxT( "a2dError_GDSIIparse" ), wxT( "gdsii parsing error" ) );
50 
51 /*
52 GDS-II:
53 <stream format> ::= HEADER BGNLIB LIBNAME [REFLIBS]
54  [FONTS] [ATTRTABLE] [GENERATION]
55  [<FormatType>] UNI TS {<Structure>}*
56  ENDLIB
57 <FormatType> ::= FORMAT | FORMAT {MASK}+ ENDMASK
58 <Structure> ::= BGNSTR STRNAME [STRCLASS]
59  {<element>}* ENDSTR
60 <element> ::= {<boundary> | <path> | <SREF> |
61  <AREF> | <text> | <node> | <bbox>}
62  {<property>}* ENDEL
63 <boundary> ::= BOUNDARY [ELFLAGS] [PLEX] LAYER
64  DATATYPE XY
65 <path> ::= PATH [ELFLAGS] [PLEX] LAYER
66  DATATYPE [PATHTYPE] [WIDTH]
67  [BGNEXTN] [ENDEXTN] XY
68 <SREF> ::= SREF [ELFLAGS] [PLEX] SNAME
69  [<strans>] XY
70 <AREF> ::= AREF [ELFLAGS] [PLEX] SNAME
71  [<strans>] COLROW XY
72 <text> ::= TEXT [ELFLAGS] [PLEX] LAYER
73  <textbody>
74 <node> ::= NODE [ELFLAGS] [PLEX] LAYER
75  NODETYPE XY
76 <box> ::= BOX [ELFLAGS] [PLEX] LAYER
77  BOXTYPE XY
78 <textbody> ::= TEXTTYPE [PRESENTATION] [PATHTYPE]
79  [WIDTH] [<strans>] XY STRING
80 <property> ::= PROPATTR PROPVALUE
81 */
82 
83 
84 /*
85 Purpose Used by GDS driver for conversions and read en write
86  GDSII elements
87 */
88 
89 // ------------- input functions -----------------
90 
91 #define MAX_G_BYTES 8 // maximum bytes a value can use
92 
93 //! array of bytes, which holds a string in GDS-II
94 struct _ARRAY
95 {
96  unsigned char array[MAX_G_BYTES];
97 };
98 struct _ARRAYB
99 {
100  char array[MAX_G_BYTES];
101 };
102 
103 //! for reading bytes from a binary GDS-II file, and convert them to internal types.
105 {
106  //! constructor reset it to 0's
107  a_union_value() { memset( array.array, 0, MAX_G_BYTES ); }
108 
109  union
110  {
111  TWO_G_BYTE_SIGNED_INTEGER two_byte_signed_integer;
112  FOUR_G_BYTE_SIGNED_INTEGER four_byte_signed_integer;
113  FOUR_G_BYTE_REAL four_byte_real;
114  EIGHT_G_BYTE_REAL eight_byte_real;
115  _ARRAY array;
116  _ARRAYB arrayc;
117  };
118 };
119 
120 // 2 bytes UNsigned integer
121 unsigned int a2dIOHandlerGDSIn::ReadUnsignedInt()
122 {
123  unsigned char swap;
124  a_union_value a_value;
125  a_value.eight_byte_real = 0;
126 
127  a2dIOHandlerStrIn::Read( a_value.arrayc.array, 2 );
128 
129 #if wxBYTE_ORDER == wxBIG_ENDIAN
130 #else
131  swap = a_value.array.array[1];
132  a_value.array.array[1] = a_value.array.array[0];
133  a_value.array.array[0] = swap;
134 #endif
135  return a_value.two_byte_signed_integer;
136 }
137 
138 
139 // 2 bytes signed integer
140 int a2dIOHandlerGDSIn::ReadInt()
141 {
142  unsigned char swap;
143  a_union_value a_value;
144  a_value.eight_byte_real = 0;
145 
146  a2dIOHandlerStrIn::Read( a_value.arrayc.array, 2 );
147 
148 #if wxBYTE_ORDER == wxBIG_ENDIAN
149 #else
150  swap = a_value.array.array[1];
151  a_value.array.array[1] = a_value.array.array[0];
152  a_value.array.array[0] = swap;
153 #endif
154  return a_value.two_byte_signed_integer;
155 }
156 
157 // 4 byte signed integer
158 long a2dIOHandlerGDSIn::ReadLong()
159 {
160  a_union_value a_value;
161  char array[4];
162 
163  // reads a GdsII variable and convers to a dos-variable
164  // the variable consist of 4 bits, numbered 0 1 2 3 , m_streami
165  // will be converted to the following sequence: 3 2 1 0
166 
167  a2dIOHandlerStrIn::Read( array, 4 );
168 
169 #if wxBYTE_ORDER == wxBIG_ENDIAN
170  a_value.array.array = array;
171 #else
172  {
173  a_value.array.array[3] = array[0];
174  a_value.array.array[2] = array[1];
175  a_value.array.array[1] = array[2];
176  a_value.array.array[0] = array[3];
177  }
178 #endif
179 
180  return a_value.four_byte_signed_integer;
181 }
182 
183 // 4 byte byte real
184 float a2dIOHandlerGDSIn::ReadFloat()
185 {
186  a_union_value a_value;
187 
188  // reads a GdsII variable and convers to a dos-variable
189  // the variable consist of 4 bits, numbered 0 1 2 3 , m_streami
190  // will be converted to the following sequence: 3 2 1 0
191 #if wxBYTE_ORDER == wxBIG_ENDIAN
192  for( short int i = 0; i <= 3; i++ )
193 #else
194  for( short int i = 3; i >= 0; i-- )
195 #endif
196  a_value.array.array[i] = GetC();
197 
198  // NOTE: in the original written code in C, a four byte real isn't convert
199  // like a eight byte real. Cause a four byte real isn't use in the
200  // gdsii, there's no problem. maybe in future versions, a four byte
201  // real must also converted. (the function gds2double must be changed
202  // for using 4 bytes instead of 8).
203 
204  return a_value.four_byte_real;
205 }
206 
207 
208 // 8 byte real
209 double a2dIOHandlerGDSIn::ReadDouble()
210 {
211  a_union_value a_value;
212  short int i;
213 
214  // reads a GdsII variable and convers to a dos-variable
215  // Reverse ordering will happen in the function gds2double
216 
217  for( i = 0; i < 8; i++ )
218  a_value.array.array[i] = GetC();
219 
220  // convert gdsii-real into a machine double
221  gds2double( a_value.array.array );
222 
223  return a_value.eight_byte_real;
224 }
225 
226 /*! PC double union
227 To convert GDSII doubles to machine doubles :
228 void gds_double( fb)
229 
230 To convert machine doubles to GDSII doubles :
231 void double_gds( fb)
232 
233 
234 GDSII floating point representation (8-byte REAL)
235 
236 SEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM
237 MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
238 
239 Sign = S=1 negatif S=0 positif
240 Expo = (E-64)^16
241 Mantisse = (1/16 <= M < 1)
242 Double value = (-1)^S * Expo * Mantisse
243 Zero = all bits of M zero
244 
245 unix (Apollo) or wxBIG_ENDIAN (8-byte REAL)
246 
247 SEEEEEEE EEEEMMMM MMMMMMMM MMMMMMMM
248 MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
249 
250 Sign = S=1 negatif S=0 positif
251 Expo = (E-1023)^2
252 Mantisse = (1.M)binary
253 Double value = (-1)^S * Expo * Mantisse
254 Zero = E=0 and M=0
255 +-Infinit = E=2047 and M=0
256 
257 notice:
258  a wxUint32 in turbo C = in memory for instance like this
259  m=40 m+1=99 m+2=94 m+3=93
260 
261  then (long) & 0xFF000000 gives the result
262  m=40 m+1=99 m+2=94 m+3=00
263 
264  in most other machine this is
265  m=00 m+1=99 m+2=94 m+3=93
266 
267  all of this is due to that the bytes of types are in reverse order
268  in memory.
269 */
270 struct bldun
271 {
272  bldun() { memset( by, 0, sizeof( wxFloat64 ) ); }
273  union
274  {
275  wxByte by[ sizeof( wxFloat64 ) / sizeof( wxByte ) ];
276  wxUint32 fl[ sizeof( wxFloat64 ) / sizeof( wxUint32 ) ];
277  wxFloat64 machdb;
278  };
279 };
280 
281 
282 //! convert a gds double to a machine double
283 //! input
284 //! arguments : unsigned char fb[] 8byte array with gds double
285 //! output
286 //! arguments : unsigned char fb[] 8byte array with machine double
287 void a2dIOHandlerGDSIn::gds2double( unsigned char fb[] )
288 {
289  bldun bld;
290  int j;
291  wxUint32 carry, e, mantissa[2], s;
292 # if defined(ultrix) || wxBYTE_ORDER == wxLITTLE_ENDIAN
293  wxUint32 swap;
294 # endif
295 
296 #if wxBYTE_ORDER == wxLITTLE_ENDIAN
297  // for turbo c real,integer,doubles are saved in memory
298  // in reverse order, so first reverse bytes
299  for ( j = 0; j < 8; j++ )
300  bld.by[j] = fb[7 - j];
301 #else
302  for ( j = 0; j < 8; j++ )
303  bld.by[j] = fb[j];
304 #endif
305 
306 
307 #ifdef vax
308  if( bld.fl[0] == 0 && bld.fl[1] == 0 ) return;
309 
310  // mask highest bit (bit 32) and shift to bit1
311  s = ( bld.fl[1] & 0x80000000L ) >> 31;
312  // same for exponent bits
313  e = ( bld.fl[1] & 0x7F000000L ) >> 24;
314 
315  // mask mantisse fo GDS double
316  mantissa[0] = bld.fl[1] & 0x00FFFFFFL;
317  mantissa[1] = bld.fl[0];
318 
319  // 2^(4*(E-64))=GDStrue exp +128 for VAX
320  e = 4 * ( e - 64 ) + 128;
321  if ( mantissa[0] == 0 && mantissa[1] == 0 && e != 0 )
322  {
323  // the number = zero
324  bld.fl[1] = 0;
325  // result back in byte array
326  for ( j = 0; j < 8; j++ )
327  fb[j] = bld.by[j];
328  return;
329  }
330 
331  // change mant. to 0.1mant
332  while( mantissa[0] < 0x00800000L )
333  {
334  // times 2
335  carry = mantissa[1] >> 31;
336  // carry to next four bytes
337  mantissa[0] = mantissa[0] << 1 | carry;
338  // bit not available become zero
339  mantissa[1] = mantissa[1] << 1;
340 
341  // without loss in accurancy
342  // so lower exponent by one
343  e--;
344  }
345 
346  // mantisse is now 0.1mant
347  // - mask highest redundant bit of mantisse
348  // - swap word (2 bytes) positions
349  // - put sign and exponent on right place
350  bld.fl[0] = ( mantissa[0] & 0x007F0000L ) >> 16 |
351  ( mantissa[0] & 0x0000FFFFL ) << 16 |
352  s << 15 | e << 7;
353 
354  // swap word positions
355  bld.fl[1] = mantissa[1] << 16 | mantissa[1] >> 16;
356  // result back in byte array
357  for ( j = 0; j < 8; j++ )
358  fb[j] = bld.by[j];
359 
360 #else
361  // convert GDSII double to _G_UNIX (Apollo) double
362  //if all is zero, it is true zero value
363  if ( bld.fl[0] == 0 && bld.fl[1] == 0 )
364  return;
365 
366 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
367  // swap the longs
368  swap = bld.fl[0] ; bld.fl[0] = bld.fl[1] ; bld.fl[1] = swap ;
369 #endif
370  // mask sign bit and shift to bit 1
371  s = ( bld.fl[0] & 0x80000000L ) >> 31;
372  // same for exponent bits
373  e = ( bld.fl[0] & 0x7F000000L ) >> 24;
374 
375  // mask mantisse bits
376  mantissa[0] = bld.fl[0] & 0x00FFFFFFL;
377  mantissa[1] = bld.fl[1];
378 
379 
380  /* THE NUMBER IS WRONG BUT IT DOES NOT HARM ME, SO I OUTCOMENTED IT
381  WE just shift what is in the mantisse some more until
382  we reach one that is set.
383  // if < 1/16 is not a right number
384  if (mantissa[0] < 0x00100000L)
385  {
386  bld.fl[0] = 0x80000000L;
387  bld.fl[1] = 0x00000000L;
388 
389 #if wxBYTE_ORDER == wxBIG_ENDIAN
390 # if defined(ultrix)
391  swap = bld.fl[0];
392  bld.fl[0] = bld.fl[1];
393  bld.fl[1] = swap;
394 # endif
395  // result back in byte array
396  for (j = 0; j < 8; j++)
397  fb[j]=bld.by[j];
398  return;
399  }
400  */
401 
402  // 2^(4*(e-64))=GDS +1023=for unix
403  e = 4 * ( e - 64 ) + 1023;
404 
405  if ( mantissa[0] == 0 && mantissa[1] == 0 && e != 0 )
406  {
407  //this is a bad number, the mantisse is total zero
408  //so i decide to return true zero as result
409  bld.fl[0] = 0x00000000L;
410  bld.fl[1] = 0x00000000L;
411 
412  // result back in byte array
413  for ( j = 0; j < 8; j++ )
414  fb[j] = bld.by[j];
415  return;
416  }
417 
418  // change mant to 1.mant
419  while ( mantissa[0] < 0x01000000L )
420  {
421  // times two
422  carry = mantissa[1] >> 31;
423  mantissa[0] = ( mantissa[0] << 1 ) | carry;
424  mantissa[1] = mantissa[1] << 1;
425 
426  // so minus one
427  e--;
428  }
429 
430  // out of range
431  if( e < 1 || e > 2047 )
432  {
433  bld.fl[0] = 0x80000000L;
434  bld.fl[1] = 0x00000000L;
435 
436 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
437  swap = bld.fl[0];
438  bld.fl[0] = bld.fl[1];
439  bld.fl[1] = swap;
440 # endif
441 
442  // result back in byte array
443  for ( j = 0; j < 8; j++ )
444  fb[j] = bld.by[j];
445  return;
446  }
447 
448  // now skip highest redundant bit of mantisseand shift mantisse
449  // to the right place in the longs
450  bld.fl[0] = ( ( mantissa[0] & 0x00FFFFFFL ) >> 4 ) | ( s << 31 ) | ( e << 20 );
451  bld.fl[1] = ( mantissa[0] << 28 ) | ( mantissa[1] >> 4 );
452 
453 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
454  swap = bld.fl[0];
455  bld.fl[0] = bld.fl[1];
456  bld.fl[1] = swap;
457 # endif
458  // result back in byte array
459  for ( j = 0; j < 8; j++ )
460  fb[j] = bld.by[j];
461 #endif // vax
462 }
463 
464 
465 //! convert a machine double to gds double
466 //! usage: void double2gds( fb )
467 //! input
468 //! arguments : unsigned char fb[] 8byte array with machine double
469 //! output
470 //! arguments : unsigned char fb[] 8byte array with gds double
471 /*! Important note:
472  The number of mantissa bit in VAX representation is
473  one less than the number of mantissa bits in GDSII
474  representation. This routine is not able to generate the
475  last 2 bits of the GDSII representation exactly.
476  There does not exist a general solution for this problem!!
477  In order to overcome the single problem that we are aware of,
478  the UNITs record that is sometimes compared to a UNITs record,
479  the solution is hard coded in this routine.
480  The last 8 bits of a number representing 1E-9 result in 53,
481  but should produce 51 (See GDSII documentation of UNIT record
482  and the given example of it).
483 
484  !! The same story holds for APOLLO and wxBIG_ENDIAN,
485  but even worse. 1E-3 results in
486  F0 for the last 8 bits instead of EF. Also corrected.
487 */
488 void a2dIOHandlerGDSOut::double2gds( unsigned char fb[] )
489 
490 {
491  bldun bld;
492 
493  union
494  {
495  wxUint32 f[2];
496  wxFloat64 check;
497  } hard_check;
498  int j;
499 
500 #ifdef vax
501  wxUint32 carry, e, f[2], s;
502 
503  // make copy into union
504  for ( j = 0; j < 8; j++ )
505  bld.by[j] = fb[j];
506 
507  hard_check.f[0] = bld.fl[0];
508  hard_check.f[1] = bld.fl[1];
509 
510  // take care of the words places
511  s = ( bld.fl[0] & 0x00008000L ) >> 15;
512  // mask sign and exponent and shift to bit1
513  e = ( bld.fl[0] & 0x00007F80L ) >> 7;
514 
515  if( s == 0 & e == 0 )
516  {
517  bld.fl[0] = bld.fl[1] = 0;
518  // result back in byte array
519  for ( j = 0; j < 8; j++ )
520  fb[j] = bld.by[j];
521  return;
522  }
523 
524  // make mant 0.1mant
525  f[0] = ( bld.fl[0] & 0x0000007FL ) << 16 | bld.fl[0] >> 16 | 0x00800000L;
526  // swap words
527  f[1] = bld.fl[1] << 16 | bld.fl[1] >> 16;
528 
529  // true exponent
530  e = e - 128;
531 
532  // new exponent 16^exp
533  while ( ( e % 4 ) != 0 )
534  {
535  // divide by two
536  carry = f[0] & 0x00000001L;
537  f[0] = f[0] >> 1;
538  f[1] = f[1] >> 1 | carry << 31;
539  // so add 1
540  e++;
541  }
542 
543  // now change 2^expo to 16^exp for GDS
544  e = e / 4 + 64;
545 
546  // put bits on right place
547  bld.fl[1] = f[0] | e << 24 | s << 31;
548  bld.fl[0] = f[1];
549 
550  // Hard coded exception begin!
551  if ( hard_check.check == 1E-9 )
552  bld.fl[0] = bld.fl[0] & 0XFFFFFF51L;
553  // End of hard coded exception
554  for ( j = 0; j < 8; j++ )
555  bld.by[j] = fb[j];
556 
557 #else
558  //convert unix (Apollo,wxLITTLE_ENDIAN) double to GDSII double
559  wxUint32 carry, f[2], s;
560 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
561  wxUint32 swap;
562 # endif
563 
564  long e;
565 
566  for ( j = 0; j < 8; j++ )
567  bld.by[j] = fb[j];
568 
569  // backup of original machine number
570  hard_check.f[0] = bld.fl[0];
571  hard_check.f[1] = bld.fl[1];
572 
573 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
574  swap = bld.fl[0];
575  bld.fl[0] = bld.fl[1];
576  bld.fl[1] = swap;
577 # endif
578 
579  // mask sign bit
580  s = ( bld.fl[0] & 0x80000000L ) >> 31;
581  // mask exponent
582  e = ( bld.fl[0] & 0x7FF00000L ) >> 20;
583 
584  // number to small
585  if( ( s == 0 ) & ( e == 0 ) )
586  {
587  // assume it is zero
588  bld.fl[0] = bld.fl[1] = 0;
589 
590 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
591  // for turbo c real, integer,d oubles are saved in memory
592  // in reverse order, so first reverse bytes
593  for ( j = 0; j < 8; j++ )
594  fb[j] = bld.by[7 - j];
595 # else
596  for ( j = 0; j < 8; j++ )
597  fb[j] = bld.by[j];
598 # endif
599 
600  return;
601  }
602 
603  // 52 bits mantisse mask
604  f[0] = ( bld.fl[0] & 0x000FFFFFL );
605  f[1] = bld.fl[1];
606 
607  // add 2 ^ 0 bit that is not yet represented because it was redundant
608  f[0] |= 0x00100000L;
609 
610  //
611  // -- Now bitposition for 2 ^ -1 is bit 12. It should be 8.
612  // -- Instead of shifting 4 bits to the left and than normalize the
613  // -- exponent by shifting 1 to 4 times to the right, there is only
614  // -- one shift of 0 to 3 time to the left. This is reflected in the
615  // -- exponent that will be 1 greater in the end
616  //
617 
618  // true exponent
619  e = e - 1023;
620 
621  // exponent should be 2^(4*newexp)
622  while( ( e % 4 ) != 0 )
623  {
624  // divide by two
625  carry = f[1] >> 31;
626  f[0] <<= 1;
627  f[1] <<= 1;
628  f[0] |= carry;
629  // so minus one
630  e--;
631  }
632 
633  // because of trick add one more
634  e = e / 4 + 65;
635 
636  // number to big are small
637  if( e < 0 || e > 127 )
638  {
639  bld.fl[0] = 0x80000000L;
640  bld.fl[1] = 0x00000000L;
641 
642 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
643  swap = bld.fl[0];
644  bld.fl[0] = bld.fl[1];
645  bld.fl[1] = swap;
646 # endif
647 
648 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
649  // for turbo c real, integer, doubles are saved in memory
650  // in reverse order, so first reverse bytes
651  for ( j = 0; j < 8; j++ )
652  fb[j] = bld.by[7 - j];
653 # else
654  for ( j = 0; j < 8; j++ )
655  fb[j] = bld.by[j];
656 # endif
657 
658  return;
659  }
660 
661  // put bits into right place for GDS
662  bld.fl[0] = f[0] | ( e << 24 ) | ( s << 31 );
663  bld.fl[1] = f[1];
664 
665  // Hard coded exception begin!
666  if( hard_check.check == 1E-3 )
667  bld.fl[1] = ( bld.fl[1] & 0XFFFFFF00L ) | 0X000000EFL;
668  if( hard_check.check == 1E-9 )
669  bld.fl[1] = ( bld.fl[1] & 0XFFFFFF00L ) | 0X00000051L;
670  // End of hard coded exception
671 
672 #if wxBYTE_ORDER == wxLITTLE_ENDIAN || defined(ultrix)
673  swap = bld.fl[0];
674  bld.fl[0] = bld.fl[1];
675  bld.fl[1] = swap;
676 # endif
677 #if wxBYTE_ORDER == wxLITTLE_ENDIAN
678  // for turbo c real,integer,doubles are saved in memory
679  // in reverse order, so first reverse bytes
680  for ( j = 0; j < 8; j++ )
681  fb[j] = bld.by[7 - j];
682 # else
683  for ( j = 0; j < 8; j++ )
684  fb[j] = bld.by[j];
685 # endif
686 
687 #endif
688 }
689 
690 //! ckecking of it is near enough to a integer number
691 /*!
692  used for deciding if rotation is there in a matrix.
693 */
694 double Check_int( double getal )
695 
696 {
697  // check if the number is very close to an integer
698  if ( ( ceil( getal ) - getal ) < 0.0001 )
699  return ceil( getal );
700 
701  else if ( ( getal - floor( getal ) ) < 0.0001 )
702 
703  return floor( getal );
704 
705  return getal;
706 
707 }
708 
709 //----------------------------------------------------------------------------------/
710 
711 // Strans
712 
713 //----------------------------------------------------------------------------------/
714 
715 
716 Strans::Strans( double a_angle, double a_scale,
717 
718  bool a_abs_angle, bool a_abs_scale, bool a_reflection )
719 {
720  m_stransflags.total = 0;
721 
722  SetAbsAngle( a_abs_angle );
723  SetAbsScale( a_abs_scale );
724  SetReflection( a_reflection );
725  SetAngle( a_angle );
726  SetScale( a_scale );
727 }
728 
729 Strans& Strans::operator=( Strans& a_strans )
730 {
731  m_stransflags.total = a_strans.m_stransflags.total;
732 
733  SetAbsAngle( bool( a_strans.m_stransflags.bits.abs_angle ) );
734  SetAbsScale( bool( a_strans.m_stransflags.bits.abs_scale ) );
735  SetReflection( bool( a_strans.m_stransflags.bits.reflection ) );
736  SetAngle( a_strans.m_angle );
737  SetScale( a_strans.m_scale );
738 
739  return *this;
740 }
741 
742 
743 bool Strans::GetStrans()
744 {
745  return m_strans_need;
746 }
747 
748 void Strans::SetAngle( double a_angle )
749 {
750  m_angle = a_angle;
751  if ( m_scale != 0 )
752  m_strans_need = true;
753 }
754 
755 
756 void Strans::SetScale( double a_scale )
757 {
758  m_scale = a_scale;
759  if ( m_scale != 1 )
760  m_strans_need = true;
761 }
762 
763 
764 void Strans::SetAbsAngle( bool b )
765 {
766  m_stransflags.bits.abs_angle = b;
767 }
768 
769 
770 void Strans::SetAbsScale( bool b )
771 {
772  m_stransflags.bits.abs_scale = b;
773 }
774 
775 
776 void Strans::SetReflection( bool b )
777 {
778  m_stransflags.bits.reflection = b;
779 }
780 
781 
782 
783 double Strans::GetAngle()
784 {
785  return m_angle;
786 }
787 
788 
789 double Strans::GetScale()
790 {
791  return m_scale;
792 }
793 
794 
795 bool Strans::GetAbsAngle()
796 {
797  return ( bool ) m_stransflags.bits.abs_angle;
798 }
799 
800 
801 bool Strans::GetAbsScale()
802 {
803  return ( bool )m_stransflags.bits.abs_scale;
804 }
805 
806 
807 bool Strans::GetReflection()
808 {
809  return ( bool )m_stransflags.bits.reflection;
810 }
811 
812 
813 void Strans::MakeStrans( const a2dAffineMatrix& matrix )
814 {
815  double scale_factor = matrix.GetValue( 0, 0 );
816  double rot_angle;
817 
818  double temp1 = matrix.GetValue( 0, 0 ); // voor het berekenen van de hoek
819 
820  double temp2 = matrix.GetValue( 0, 1 ); //
821  bool check_1 = ( matrix.GetValue( 0, 0 ) < 0 ); // om te kijken of er horizontaal gespiegeld moet worden
822 
823  bool check_2 = ( matrix.GetValue( 1, 1 ) < 0 ); // verticaal
824 
825  m_strans_need = false;
826 
827  if ( check_1 )
828  {
829  // Reflection horizontal (in y)
830  SetReflection( true );
831  rot_angle = 180;
832  SetAngle( rot_angle );
833  m_strans_need = true;
834  }
835 
836  if ( check_2 )
837  {
838  // Reflection vertical (in x)
839  SetReflection( !GetReflection() );
840  m_strans_need = true;
841  }
842 
843 
844  if ( matrix.GetValue( 0, 1 ) != 0 )
845  {
846  // Rotation
847  rot_angle = Check_int( atan2( temp2, temp1 ) * 180 / wxPI ); // kijk of dit een integer is (met bepaalde toegestane afwijking)
848 
849  SetAngle( rot_angle );
850  if ( rot_angle != 90 && rot_angle != -90 )
851  scale_factor = matrix.GetValue( 0, 0 ) / cos( ( rot_angle / 180 ) * wxPI );
852  else
853  scale_factor = matrix.GetValue( 1, 0 ) / sin( ( rot_angle / 180 ) * wxPI ); // er kan nl. niet door 0 gedeeld worden !
854  m_strans_need = true;
855  }
856 
857 
858 
859  // scale
860  scale_factor = Check_int( scale_factor );
861 
862  if ( scale_factor < 0 ) // schaling altijd positief
863  scale_factor = -scale_factor;
864 
865  if ( scale_factor != 1 ) // niet schalen bij 1
866  {
867  SetScale( scale_factor );
868  m_strans_need = true;
869  }
870 
871 }
872 
873 //----------------------------------------------------------------------------------/
874 // a2dIOHandlerGDSIn
875 //----------------------------------------------------------------------------------/
876 
877 a2dIOHandlerGDSIn::a2dIOHandlerGDSIn()
878 {
879  m_fontType = a2dFONT_STROKED;
880  m_docClassInfo = &a2dCanvasDocument::ms_classInfo;
881  m_refMaxx = 10;
882  m_dx = m_dy = 0;
883  m_asCameleons = false;
884 }
885 
886 a2dIOHandlerGDSIn::~a2dIOHandlerGDSIn()
887 {
888 }
889 
891 {
893  if ( m_doc )
894  a2dCanvasGlobals->GetHabitat()->SetAberPolyToArc( double( a2dCanvasGlobals->GetHabitat()->GetAberPolyToArc() ) / m_doc->GetUnitsScale() );
895 }
896 
898 {
900 }
901 
902 bool a2dIOHandlerGDSIn::CanLoad( a2dDocumentInputStream& stream, const wxObject* obj, wxClassInfo* docClassInfo )
903 {
904  if ( obj && !wxDynamicCast( obj, a2dCanvasDocument ) )
905  return false;
906 
907  if ( docClassInfo && m_docClassInfo && !docClassInfo->IsKindOf( m_docClassInfo ) )
908  return false;
909 
910  m_streami = &stream;
911  m_doc = 0;
912 
913  SeekI( 0 );
914 
915  m_recordsize = 0;
916  m_recordtype = 0;
917  m_datatype = 0;
918  m_back = false;
919 
920  if ( !ReadHeader( GDS_HEADER ) )
921  {
922  SeekI( 0 );
923  return false;
924  }
925  SeekI( 0 );
926  return true;
927 }
928 
929 bool a2dIOHandlerGDSIn::LinkReferences()
930 {
931  bool res = a2dIOHandler::LinkReferences();
932  {
933  //search in the root object for the childs that have the bin flag set,
934  //which means they are referenced, and can be deleted.
935  //All othere are top structures.
937  a2dCanvasObjectList::iterator rootchild = root->GetChildObjectList()->begin();
938  while ( rootchild != root->GetChildObjectList()->end() )
939  {
940  a2dCanvasObjectList::iterator delnode = rootchild;
941  rootchild++;
942  if ( ( *delnode )->GetCheck() )
943  {
944  root->GetChildObjectList()->erase( delnode );
945  }
946  }
947  }
948  return res;
949 }
950 
951 bool a2dIOHandlerGDSIn::Load( a2dDocumentInputStream& stream, wxObject* doc )
952 {
953  m_streami = &stream;
955  InitializeLoad();
956 
957  wxString path;
958  path = m_doc->GetFilename().GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ) + m_doc->GetFilename().GetName() + wxT( ".cvg" );
959  if ( wxFileExists( path ) )
960  m_doc->LoadLayers( path );
961 
963 
964  m_recordsize = 0;
965  m_recordtype = 0;
966  m_datatype = 0;
967  m_back = false;
968 
969  m_mapping.resize( wxMAXLAYER );
970 
971  unsigned int i;
972  for ( i = 0; i < wxMAXLAYER; i++ )
973  m_mapping[i] = -1;
974  for ( i = 0; i < wxMAXLAYER; i++ )
975  {
976  if ( m_doc->GetLayerSetup()->GetLayerIndex()[i] != wxNullLayerInfo )
977  {
978  int layerIndex = m_doc->GetLayerSetup()->GetInMapping( i );
979  wxASSERT_MSG( layerIndex >= 0 && layerIndex < wxMAXLAYER, _( "InMap must be > wxMAXLAYER" ) );
980  m_mapping[ m_doc->GetLayerSetup()->GetInMapping( i ) ] = i;
981  }
982  }
983 
984  for ( i = 0; i < wxMAXLAYER; i++ )
985  if ( m_mapping[i] == -1 )
986  m_mapping[i] = 0;
987 
988  try
989  {
990  ReadGdsII();
991  }
992  catch ( GDS_Error& _error )
993  {
994  ResetLoad();
995  a2dDocviewGlobals->ReportErrorF( a2dError_NotSpecified, _( "error in GDSII file \n %s \n" ), _error.GetErrorMessage().c_str() );
996  return false;
997  }
998 
999  ResetLoad();
1000  return true;
1001 }
1002 
1003 // GdsII --------------------------------------------------------------------
1004 void a2dIOHandlerGDSIn::ReadGdsII()
1005 {
1006  //The a2dObject::m_check is used for removing structure from the rootobject after resolving references.
1007  //when a new document is filled this would not be needed, since all m_check flags are default set false.
1008  //But maybe for the future import it is important to do.
1009 
1010  a2dWalker_SetCheck setp( false );
1011  setp.Start( m_doc->GetDrawing()->GetRootObject() );
1012 
1014 
1015  // Grammar: HEADER BGNLIB LIBNAME [REFLIBS] [FONTS]
1016  // [ATTRTABLE] [GENERATION] [<FormatType>]
1017  // UNITS {<Structure>}* ENDLIB
1018  //
1019  if ( !ReadHeader( GDS_HEADER ) )
1020  throw GDS_Error( _( "GDS_HEADER record missing (in GDSII)" ), _( "Error" ) );
1021 
1022  wxString s;
1023  s.Printf("%d", ReadInt());
1024  m_doc->SetVersion( s );
1025 
1026  if ( !ReadBgnlib() )
1027  throw GDS_Error( _( "BGNLIB record missing (in GDSII)" ) );
1028 
1029  if ( !ReadLibrarySettings() )
1030  throw GDS_Error( _( "LIBNAME missing (in GDSII)" ) );
1031 
1032  if ( m_asCameleons )
1033  {
1034  while ( ReadCameleonStructure( m_doc->GetDrawing()->GetRootObject() ) )
1035  {
1036  }
1037  }
1038  else
1039  {
1040  while ( ReadStructure( m_doc->GetDrawing()->GetRootObject() ) )
1041  {
1042  }
1043  }
1044 
1045  if ( !ReadHeader( GDS_ENDLIB ) )
1046  throw GDS_Error( _( "GDS_ENDLIB record missing (in GDSII)" ), _( "Error" ) );
1047 
1048  //references to other structure are known
1049  //by name now. Set the pointers in those references
1050  //to the right structures
1051  LinkReferences(); //GDS links on Name
1052 
1053  if ( m_asCameleons )
1054  {
1055  m_dx = m_dy = 0;
1056 
1057  m_doc->GetDrawing()->SetDrawingId( a2dDrawing::sm_cameleonrefs );
1058  if ( m_doc->GetDrawing()->GetRootObject()->GetChildObjectsCount() == 0 )
1059  throw GDS_Error( wxT( "no structures found" ) );
1060 
1062 
1063  a2dCameleon* topcam = NULL;
1064  a2dCanvasObjectList::iterator rootchild = m_doc->GetDrawing()->GetRootObject()->GetChildObjectList()->begin();
1065  while ( rootchild != m_doc->GetDrawing()->GetRootObject()->GetChildObjectList()->end() )
1066  {
1067  a2dCameleon* ref = wxDynamicCast( (*rootchild).Get(), a2dCameleon );
1068  if ( ref )
1069  {
1070  a2dLayout* layout = ref->GetAppearance<a2dDiagram>();
1071  layout->GetDrawing()->SetRootRecursive();
1072  if ( ! layout->GetCheck() )
1073  {
1074  topcam = ref;
1075  m_doc->SetTopCameleon( topcam );
1076  m_doc->SetShowObject( layout->GetDrawing()->GetRootObject() );
1077  }
1078  }
1079  rootchild++;
1080  }
1081 
1082  /*
1083  a2dCameleon* cam;
1084  if ( topcam )
1085  {
1086  cam = topcam;
1087  a2dLayout* layout = cam->GetAppearance<a2dDiagram>();
1088  a2dSmrtPtr<class a2dDrawing > Structure = layout->GetDrawing();
1089  m_doc->SetRootObject( Structure );
1090  }
1091  else
1092  throw GDS_Error( wxT( "no non referenced structure found" ) );
1093  */
1094  }
1095  else
1096  {
1097  if ( m_doc->GetDrawing()->GetRootObject()->GetChildObjectsCount() != 1 )
1098  m_doc->SetMultiRoot();
1099  else
1102  }
1103 }
1104 
1105 // Bgnlib -------------------------------------------------------------------
1106 bool a2dIOHandlerGDSIn::ReadBgnlib()
1107 {
1108  if ( !ReadHeader( GDS_BGNLIB ) )
1109  return( false );
1110 
1111  int year;
1112  int month;
1113  int day;
1114  int hour;
1115  int minute;
1116  int second;
1117 
1118  year = ReadInt();
1119  month = ReadInt() - 1;
1120  day = ReadInt();
1121  hour = ReadInt();
1122  minute = ReadInt();
1123  second = ReadInt();
1124 
1125  m_doc->GetModificationTime().Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
1126 
1127  year = ReadInt();
1128  month = ReadInt() - 1;
1129  day = ReadInt();
1130  hour = ReadInt();
1131  minute = ReadInt();
1132  second = ReadInt();
1133 
1134  m_doc->GetAccessTime().Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
1135 
1136  return( true );
1137 }
1138 
1139 // Library ------------------------------------------------------------------
1140 bool a2dIOHandlerGDSIn::ReadLibrarySettings()
1141 {
1142  if ( !ReadHeader( GDS_LIBNAME ) )
1143  throw GDS_Error( _( "GDS_LIBNAME record missing (in GDSII)" ), _( "Error" ) );
1144 
1145  wxString libname;
1146  ReadString( libname );
1147 
1148  m_doc->SetLibraryName( libname );
1149 
1150  if ( ReadHeader( GDS_REFLIBS ) )
1151  SkipData();
1152 
1153  if ( ReadHeader( GDS_FONTS ) )
1154  SkipData();
1155 
1156  if ( ReadHeader( GDS_ATTRTABLE ) )
1157  SkipData();
1158 
1159  if ( ReadHeader( GDS_GENERATIONS ) )
1160  SkipData();
1161 
1162  if ( ReadHeader( GDS_FORMAT ) )
1163  SkipData();
1164 
1165  if ( !ReadHeader( GDS_UNITS ) )
1166  throw GDS_Error( _( "UNITS missing (in GDSII)" ) );
1167 
1168  m_userunits_out = ReadDouble();
1169  m_doc->SetUnitsAccuracy( m_userunits_out );
1170  double value1;
1171  value1 = ReadDouble();
1172  double metersScale = value1 / m_userunits_out;
1173  m_doc->SetUnitsScale( metersScale );
1174 
1175  a2dDoMu unit = a2dDoMu( 1, 1 );
1176  m_doc->SetUnits( unit.GetMultiplierString() );
1177  unit = a2dDoMu( 1, metersScale );
1178  m_doc->SetUnits( unit.GetMultiplierString() );
1179 
1180  return true;
1181 }
1182 
1183 
1185 {
1186  if ( m_back )
1187  {
1188  if ( m_recordtype == type )
1189  {
1190  m_back = false;
1191  return true;
1192  }
1193  }
1194  else
1195  {
1196  if ( Eof() )
1197  throw GDS_Error( _( "Unexpected end of GDSII-file!" ), _( "Driver Error" ) );
1198 
1199  m_recordsize = ReadUnsignedInt();
1200  m_recordtype = GetC();
1201  m_datatype = GetC();
1202 
1203  m_recordsize -= ( TWO_G_BYTE_UNSIGNED_INTEGER ) GDS_HEADERSIZE;
1204 
1205  if ( m_recordtype == type )
1206  return true;
1207  if ( m_recordtype > 56 )
1208  {
1209 // throw GDS_Error("Unknown Record Type! Record is not part of the GDS-II Stream Format v5.2","Driver Error", 9, 0);
1210  SkipData();
1211  }
1212  m_back = true;
1213  }
1214  return false;
1215 }
1216 
1218 {
1219  for ( int i = 0; i < m_recordsize; i++ )
1220  {
1221  GetC();
1222  }
1223 
1224  m_back = false;
1225  m_recordsize = 0;
1226  m_recordtype = 0;
1227  m_datatype = 0;
1228 }
1229 
1230 void a2dIOHandlerGDSIn::ReadString( wxString& a_string )
1231 {
1232  wxString header;
1233  char buf[512];
1234  int last_read = a2dIOHandlerStrIn::Read( buf, m_recordsize );
1235 
1236  if ( buf[m_recordsize - 1] == '\0' )
1237  a_string = wxString( buf, wxConvUTF8, m_recordsize - 1 );
1238  else
1239  a_string = wxString( buf, wxConvUTF8, m_recordsize );
1240 }
1241 
1242 // Read Element -------------------------------------------------------------
1243 bool a2dIOHandlerGDSIn::ReadElement( a2dCanvasObject* parent )
1244 {
1245  if ( ReadBoundary( parent ) ||
1246  ReadPath( parent ) ||
1247  ReadStructureReference( parent ) ||
1248  ReadArrayReference( parent ) ||
1249  ReadText( parent ) ||
1250  ReadNode( parent ) ||
1251  ReadBox( parent ) )
1252  {
1253  }
1254  else
1255  return false;
1256 
1257  while ( ReadProperty() )
1258  ;
1259 
1260  if ( !ReadHeader( GDS_ENDEL ) )
1261  throw GDS_Error( _( "ENDEL missing (in Element)" ) );
1262 
1263  return true;
1264 }
1265 
1266 
1267 // Property -----------------------------------------------------------------
1268 bool a2dIOHandlerGDSIn::ReadProperty()
1269 {
1270  int i;
1271  if ( ReadHeader( GDS_PROPATTR ) )
1272  {
1273  // Read Property Attribute
1274  int propattr;
1275  propattr = ReadInt();
1276 
1277  if ( Eof() )
1278  throw GDS_Error( _( "Unexpected end of GDSII-file!" ), _( "GDSII Input parsing Error" ) );
1279 
1280  m_back = false;
1281 
1282  // Check (for) Property Value
1283  if ( !ReadHeader( GDS_PROPVALUE ) )
1284  throw GDS_Error( _( "PROPVALUE missing (in Property)" ) );
1285 
1286  // Read Property Value
1287  G_BYTE propval[126];
1288  for ( i = 0; i < m_recordsize; i++ )
1289  {
1290  if ( Eof() )
1291  throw GDS_Error( _( "Unexpected end of GDSII-file!" ), _( "GDSII Input parsing Error" ) );
1292 
1293  propval[i] = GetC();
1294  }
1295  m_back = false;
1296  // End string
1297  if ( i <= 126 )
1298  propval[i] = 0;
1299 
1300  return true; // Found one!
1301  }
1302  return false; // Didn't find one.
1303 }
1304 
1305 
1306 // Boundary -----------------------------------------------------------------
1307 bool a2dIOHandlerGDSIn::ReadBoundary( a2dCanvasObject* parent )
1308 {
1309  // Grammar: BOUNDARY [ELFLAGS] [PLEX] LAYER DATATYPE XY
1310  if ( !ReadHeader( GDS_BOUNDARY ) )
1311  return false;
1312 
1313  // Create a new Boundary
1314  //a2dSmrtPtr<a2dPolygon> _Boundary = new a2dPolygon();
1315  a2dSmrtPtr<a2dPolygonL> _Boundary = new a2dPolygonL();
1316 
1317  ReadElflags( _Boundary );
1318 
1319  if ( ReadHeader( GDS_PLEX ) )
1320  SkipData();
1321 
1322  if ( !ReadLayer( _Boundary ) )
1323  throw GDS_Error( _( "Boundary: LAYER missing (in GDS-file)" ) );
1324 
1325  if ( !ReadHeader( GDS_DATATYPE ) )
1326  throw GDS_Error( _( "Boundary: DATATYPE missing (in GDS-file)" ) );
1327 
1328  SetDataTypeProperty( _Boundary, ReadInt() );
1329 
1330  if ( m_doc->GetLayerSetup()->GetRead( _Boundary->GetLayer() ) )
1331  {
1332  if ( !Read( _Boundary ) )
1333  throw GDS_Error( _( "Header: XY missing (in Boundary)" ) );
1334 
1335  parent->Append( _Boundary );
1336  }
1337  else
1338  {
1339  ReadHeader( GDS_XY );
1340  SkipData();
1341  }
1342 
1343  return true;
1344 }
1345 
1346 // Path ---------------------------------------------------------------------
1347 bool a2dIOHandlerGDSIn::ReadPath( a2dCanvasObject* parent )
1348 {
1349  // Grammar: PATH [ELFLAGS] [PLEX] LAYER DATATYPE
1350  // [PATHTYPE] [WIDTH] [BGNEXTN] [ENDEXTN] XY
1351 
1352  if ( !ReadHeader( GDS_PATH ) )
1353  return false;
1354 
1355  // Create a new Polyline
1357 
1358  ReadElflags( path );
1359 
1360  if ( ReadHeader( GDS_PLEX ) )
1361  SkipData();
1362 
1363  if ( !ReadLayer( path ) )
1364  throw GDS_Error( _( "record LAYER missing (in Path)" ) );
1365 
1366  if ( !ReadHeader( GDS_DATATYPE ) )
1367  throw GDS_Error( _( "record DATATYPE missing (in Path)" ) );
1368 
1369  SetDataTypeProperty( path, ReadInt() );
1370 
1371  if ( ReadHeader( GDS_PATHTYPE ) )
1372  path->SetPathType( ( a2dPATH_END_TYPE ) ReadInt() );
1373 
1374  if ( ReadHeader( GDS_WIDTH ) )
1375  path->SetContourWidth( ReadLong() * m_userunits_out );
1376 
1377  if ( ReadHeader( GDS_BGNEXTN ) )
1378  SkipData();
1379 
1380  if ( ReadHeader( GDS_ENDEXTN ) )
1381  SkipData();
1382 
1383  if ( m_doc->GetLayerSetup()->GetRead( path->GetLayer() ) )
1384  {
1385  if ( !Read( path->GetSegments() ) )
1386  throw GDS_Error( _( "Header: XY missing (in Path)" ) );
1387  parent->Append( path );
1388  // with arrow heads draw with polyline, this is not so good.
1389  //path->RemoveRedundantPoints();
1390  }
1391  else
1392  {
1393  ReadHeader( GDS_XY );
1394  SkipData();
1395  }
1396 
1397  return true;
1398 }
1399 
1400 // Text ---------------------------------------------------------------------
1401 bool a2dIOHandlerGDSIn::ReadText( a2dCanvasObject* parent )
1402 {
1403  // Grammar: TEXT [ELFLAGS] [PLEX] LAYER
1404  // TEXTTYPE [PRESENTATION] [PATHTYPE] [WIDTH]
1405  // [<strans>] XY STRING
1406  //
1407  // <strans> = STRANS [MAG] [ANGLE]
1408 
1409  if ( !ReadHeader( GDS_TEXT ) )
1410  return false;
1411 
1412 
1413  // Elflags
1414  // instead of ReadElflags(Text) for speed
1415  int elflags = 0;
1416  if ( ReadHeader( GDS_ELFLAGS ) )
1417  elflags = ReadInt();
1418 
1419  if ( ReadHeader( GDS_PLEX ) )
1420  SkipData();
1421 
1422  int layer;
1423  if ( !ReadLayer( layer ) )
1424  throw GDS_Error( _( "Text: LAYER is missing (in GDS-file)" ) );
1425 
1426  // <textbody> ::= TEXTTYPE [PRESENTATION] [PATHTYPE]
1427  // [WIDTH] [<strans>] XY STRING
1428  // Must be there
1429  if ( !ReadHeader( GDS_TEXTTYPE ) )
1430  throw GDS_Error( _( "Text: TEXTBODY is missing (in GDS-file)" ) );
1431 
1432  int texttype = ReadInt();
1433  int presentation = 0;
1434  int pathtype = 0;
1435  long textHeight = 0;
1436  // Optional
1437  if ( ReadHeader( GDS_PRESENTATION ) )
1438  presentation = ReadInt();
1439 
1440  if ( ReadHeader( GDS_PATHTYPE ) )
1441  pathtype = ReadInt();
1442 
1443  if ( ReadHeader( GDS_WIDTH ) )
1444  {
1445  // in MDS this is generated along with the MAG record holding the same,
1446  // so igore it here.
1447  // Text->SetTextHeight( ReadLong() * m_userunits_out * m_scale_out );
1448  textHeight = ReadLong();
1449  }
1450 
1451  Strans Strans;
1452  ReadStrans( Strans );
1453 
1454  if ( !ReadHeader( GDS_XY ) )
1455  throw GDS_Error( _( "Text: XY is missing (in GDS-file)" ) );
1456 
1457  a2dPoint2D point;
1458  Read( point );
1459 
1460  a2dAffineMatrix relative_matrix;
1461 
1462  // Ok, now we have a strans, but we want to work with a matrix,
1463  // so let's convert it to one:
1464 
1465  // Mirror in X if necessary
1466  if ( Strans.GetReflection() )
1467  relative_matrix.Mirror();
1468 
1469  // Rotate if necessary
1470  if ( Strans.GetAbsAngle() == 0 )
1471  relative_matrix.Rotate( Strans.GetAngle(), 0, 0 );
1472 
1473  // Scale if necessary
1474  if ( Strans.GetAbsScale() == 0 )
1475  {
1476  //WE DIRECTLY SET IT TO TEXT HEIGHT
1477  //double scale = Strans.GetScale();
1478  //relative_matrix.Scale(scale, scale, 0, 0);
1479  }
1480 
1481  // Translate2D over XY from the structrereference
1482  relative_matrix.Translate( point.m_x, point.m_y );
1483 
1484  if ( !ReadHeader( GDS_STRING ) )
1485  throw GDS_Error( _( "Text: STRING is missing (in GDS-file)" ) );
1486 
1487  wxString a_string;
1488  ReadString( a_string );
1489  a_string.Replace( wxT( "\t" ), wxT( " " ) );
1490 
1491  // Create a new Text
1492  a2dSmrtPtr<a2dTextGDS> Text = new a2dTextGDS( m_fontType, a_string, Strans.GetScale() * a2dTextGDS::GetFontScaleFactor(), presentation );
1493  //Text->SetLineSpacing( Text->GetLineHeight() / 119.25 );
1494  Text->SetLayer( m_mapping[layer] );
1495  Text->SetTextType( texttype );
1496  Text->SetPathtype( ( TEXT_PATHTYPE )pathtype );
1497  Text->SetTransformMatrix( relative_matrix );
1498 
1499 #ifdef _G_UNIX
1500  Text->SetTemplate( ( bool ) ( elflags && 2 ) );
1501  Text->SetExternal( ( bool ) ( elflags && 1 ) );
1502 #else
1503  Text->SetTemplate( ( bool ) ( elflags && 1 ) );
1504  Text->SetExternal( ( bool ) ( elflags && 2 ) );
1505 #endif
1506 
1507 
1508  if ( m_doc->GetLayerSetup()->GetRead( Text->GetLayer() ) )
1509  parent->Append( Text );
1510 
1511  return true;
1512 }
1513 
1514 
1515 // StructureReference -------------------------------------------------------
1516 bool a2dIOHandlerGDSIn::ReadStructureReference( a2dCanvasObject* parent )
1517 {
1518 // <SREF> ::= SREF [ELFLAGS] [PLEX] SNAME
1519 // [<strans>] XY
1520 // <strans> ::= STRANS [MAG] [ANGLE]
1521 
1522  if ( m_asCameleons )
1523  return ReadStructureCameleonReference( parent );
1524 
1525  if ( !ReadHeader( GDS_SREF ) )
1526  return false;
1527 
1528  a2dPoint2D point;
1529  a2dAffineMatrix relative_matrix;
1531 
1532  try
1533  {
1534 
1535  ReadElflags( sref );
1536 
1537  if ( ReadHeader( GDS_PLEX ) )
1538  SkipData();
1539 
1540  if ( !ReadHeader( GDS_SNAME ) )
1541  throw GDS_Error( _( "Header: SNAME missing (in Structure Reference)" ) );
1542 
1543  wxString strname;
1544  ReadString( strname );
1545  sref->SetName( strname );
1546 
1547  Strans strans;
1548  ReadStrans( strans );
1549 
1550  if ( !ReadHeader( GDS_XY ) )
1551  throw GDS_Error( _( "Header: XY missing (in Structure Reference)" ) );
1552 
1553  Read( point );
1554 
1555  // Ok, now we have a strans, but we want to work with a matrix,
1556  // so let's convert it to one:
1557 
1558  // Mirror in X if necessary
1559  if ( strans.GetReflection() )
1560  relative_matrix.Mirror();
1561 
1562  // Rotate if necessary
1563  if ( strans.GetAbsAngle() == 0 )
1564  relative_matrix.Rotate( strans.GetAngle(), 0, 0 );
1565 
1566  // Scale if necessary
1567  if ( strans.GetAbsScale() == 0 )
1568  {
1569  double scale = strans.GetScale();
1570  relative_matrix.Scale( scale, scale, 0, 0 );
1571  }
1572 
1573  // Translate2D over XY from the structure reference
1574  relative_matrix.Translate( point.m_x, point.m_y );
1575 
1576  sref->SetTransformMatrix( relative_matrix );
1577 
1578  parent->Append( sref );
1579  ResolveOrAddLink( sref.Get(), sref->GetName() );
1580  }
1581  catch ( GDS_Error& _error )
1582  {
1583  throw _error;
1584  }
1585 
1586  return true;
1587 }
1588 
1589 // StructureReference -------------------------------------------------------
1590 bool a2dIOHandlerGDSIn::ReadStructureCameleonReference( a2dCanvasObject* parent )
1591 {
1592 // <SREF> ::= SREF [ELFLAGS] [PLEX] SNAME
1593 // [<strans>] XY
1594 // <strans> ::= STRANS [MAG] [ANGLE]
1595 
1596  if ( !ReadHeader( GDS_SREF ) )
1597  return false;
1598 
1599  a2dPoint2D point;
1600  a2dAffineMatrix relative_matrix;
1602 
1603  try
1604  {
1605 
1606  ReadElflags( sref );
1607 
1608  if ( ReadHeader( GDS_PLEX ) )
1609  SkipData();
1610 
1611  if ( !ReadHeader( GDS_SNAME ) )
1612  throw GDS_Error( _( "Header: SNAME missing (in Structure Reference)" ) );
1613 
1614  wxString strname;
1615  ReadString( strname );
1616  sref->SetAppearanceName( strname + wxT(":layout") );
1617  sref->SetName( strname );
1618 
1619  Strans strans;
1620  ReadStrans( strans );
1621 
1622  if ( !ReadHeader( GDS_XY ) )
1623  throw GDS_Error( _( "Header: XY missing (in Structure Reference)" ) );
1624 
1625  Read( point );
1626 
1627  // Ok, now we have a strans, but we want to work with a matrix,
1628  // so let's convert it to one:
1629 
1630  // Mirror in X if necessary
1631  if ( strans.GetReflection() )
1632  relative_matrix.Mirror();
1633 
1634  // Rotate if necessary
1635  if ( strans.GetAbsAngle() == 0 )
1636  relative_matrix.Rotate( strans.GetAngle(), 0, 0 );
1637 
1638  // Scale if necessary
1639  if ( strans.GetAbsScale() == 0 )
1640  {
1641  double scale = strans.GetScale();
1642  relative_matrix.Scale( scale, scale, 0, 0 );
1643  }
1644 
1645  // Translate2D over XY from the structure reference
1646  relative_matrix.Translate( point.m_x, point.m_y );
1647 
1648  sref->SetTransformMatrix( relative_matrix );
1649 
1650  parent->Append( sref );
1651  ResolveOrAddLink( sref.Get(), sref->GetName() );
1652  }
1653  catch ( GDS_Error& _error )
1654  {
1655  throw _error;
1656  }
1657 
1658  return true;
1659 }
1660 
1661 // Arrayreference -----------------------------------------------------------
1662 bool a2dIOHandlerGDSIn::ReadArrayReference( a2dCanvasObject* parent )
1663 {
1664  // Grammar: AREF [ELFLAGS] [PLEX] SNAME [<strans>]
1665  // COLROW XY
1666 
1667  if ( !ReadHeader( GDS_AREF ) )
1668  return false;
1669 
1670  a2dPoint2D Point;
1671  a2dAffineMatrix relative_matrix;
1672  a2dPoint2D HorPoint;
1673  a2dPoint2D VerPoint;
1674 
1675  // Create a new Aref
1677  try
1678  {
1679  ReadElflags( arrayref );
1680 
1681  if ( ReadHeader( GDS_PLEX ) )
1682  SkipData();
1683 
1684  if ( !ReadHeader( GDS_SNAME ) )
1685  throw GDS_Error( _( "Header: SNAME missing (in Structure Reference)" ) );
1686 
1687  wxString strname;
1688  ReadString( strname );
1689  arrayref->SetName( strname );
1690 
1691  Strans strans;
1692  ReadStrans( strans );
1693 
1694  if ( !ReadHeader( GDS_COLROW ) )
1695  throw GDS_Error( _( "Header: COLROW missing (in Array Reference)" ) );
1696 
1697  int columns = ReadInt();
1698  arrayref->SetColumns( columns );
1699 
1700  int rows = ReadInt();
1701  arrayref->SetRows( rows );
1702 
1703 
1704  if ( !ReadHeader( GDS_XY ) )
1705  throw GDS_Error( _( "Header: XY missing (in Array Reference)" ) );
1706 
1707  Read( Point );
1708  Read( HorPoint );
1709  Read( VerPoint );
1710 
1711  arrayref->SetHorzSpace( sqrt( pow( HorPoint.m_x - Point.m_x, 2 ) + pow( HorPoint.m_y - Point.m_y, 2 ) ) / columns );
1712  arrayref->SetVertSpace( sqrt( pow( VerPoint.m_x - Point.m_x, 2 ) + pow( VerPoint.m_y - Point.m_y, 2 ) ) / rows );
1713 
1714  // Ok, now we have a strans, but we want to work with a matrix,
1715  // so let's convert it to one:
1716 
1717  // Mirror in X if necessary
1718  if ( strans.GetReflection() )
1719  relative_matrix.Mirror();
1720 
1721  // Rotate if necessary
1722  if ( strans.GetAbsAngle() == 0 )
1723  relative_matrix.Rotate( strans.GetAngle(), 0, 0 );
1724 
1725  // Scale if necessary
1726  if ( strans.GetAbsScale() == 0 )
1727  {
1728  EIGHT_G_BYTE_REAL scale = strans.GetScale();
1729  relative_matrix.Scale( scale, scale, 0, 0 );
1730  }
1731 
1732  // Translate2D over XY from the structurereference
1733  relative_matrix.Translate( Point.m_x, Point.m_y );
1734  arrayref->SetTransformMatrix( relative_matrix );
1735 
1736  parent->Append( arrayref );
1737  ResolveOrAddLink( arrayref.Get(), arrayref->GetName() );
1738  }
1739  catch ( GDS_Error& _error )
1740  {
1741  throw _error;
1742  }
1743 
1744  return true;
1745 }
1746 
1747 
1748 bool a2dIOHandlerGDSIn::ReadNode( a2dCanvasObject* WXUNUSED( parent ) )
1749 {
1750  // not implemented
1751  return false;
1752 }
1753 
1754 
1755 // Box ----------------------------------------------------------------------
1756 bool a2dIOHandlerGDSIn::ReadBox( a2dCanvasObject* parent )
1757 {
1758  // Grammar: BOX [ELFLAGS] [PLEX] LAYER BOXTYPE XY
1759  if ( !ReadHeader( GDS_BOX ) )
1760  return false;
1761 
1762  // Create a new Boundary
1763  a2dRect* Box = new a2dRect();
1764 
1765  ReadElflags( Box );
1766 
1767  if ( ReadHeader( GDS_PLEX ) )
1768  SkipData();
1769 
1770  if ( !ReadLayer( Box ) )
1771  throw GDS_Error( _( "Box: LAYER missing (in GDS-file)" ) );
1772 
1773  if ( !ReadHeader( GDS_BOXTYPE ) )
1774  throw GDS_Error( _( "Box: BOXTYPE missing (in GDS-file)" ) );
1775 
1776  Box->SetBoxType( ReadInt() );
1777 
1778  if ( !ReadHeader( GDS_XY ) )
1779  return false;
1780 
1781  int points = m_recordsize / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) );
1782 
1783  if ( points != 5 )
1784  throw GDS_Error( _( "Wrong number of points in BOX XY." ), _( "Fatal GDSII error" ) );
1785 
1786  a2dPoint2D seg;
1787  Read( seg );
1788  a2dPoint2D seg2;
1789  Read( seg2 );
1790  a2dPoint2D seg3;
1791  Read( seg3 );
1792  a2dPoint2D seg4;
1793  Read( seg4 );
1794  a2dPoint2D seg5;
1795  Read( seg5 ); // Last point matches first one read
1796 
1797  double minx, miny, maxx, maxy;
1798 
1799  minx = maxx = seg.m_x;
1800  miny = maxy = seg.m_y;
1801 
1802  minx = wxMin( minx, seg2.m_x );
1803  maxx = wxMax( maxx, seg2.m_x );
1804  miny = wxMin( miny, seg2.m_y );
1805  maxy = wxMax( maxy, seg2.m_y );
1806 
1807  minx = wxMin( minx, seg3.m_x );
1808  maxx = wxMax( maxx, seg3.m_x );
1809  miny = wxMin( miny, seg3.m_y );
1810  maxy = wxMax( maxy, seg3.m_y );
1811 
1812  minx = wxMin( minx, seg4.m_x );
1813  maxx = wxMax( maxx, seg4.m_x );
1814  miny = wxMin( miny, seg4.m_y );
1815  maxy = wxMax( maxy, seg4.m_y );
1816 
1817  Box->SetWidth( fabs( maxx - minx ) );
1818  Box->SetHeight( fabs( maxy - miny ) );
1819  Box->SetPosXY( minx, miny );
1820 
1821  if ( m_doc->GetLayerSetup()->GetRead( Box->GetLayer() ) )
1822  parent->Append( Box );
1823 
1824  return true;
1825 }
1826 
1827 // Elflags ------------------------------------------------------------------
1828 bool a2dIOHandlerGDSIn::ReadElflags( a2dCanvasObject* object )
1829 {
1830  if ( !ReadHeader( GDS_ELFLAGS ) )
1831  return false;
1832 
1833  int value;
1834  value = ReadInt();
1835 
1836 #ifdef _G_UNIX
1837  object->SetTemplate( ( bool ) ( value && 2 ) );
1838  object->SetExternal( ( bool ) ( value && 1 ) );
1839 #else
1840  object->SetTemplate( ( bool ) ( value && 1 ) );
1841  object->SetExternal( ( bool ) ( value && 2 ) );
1842 #endif
1843 
1844  return true;
1845 }
1846 
1847 // Layer --------------------------------------------------------------------
1848 bool a2dIOHandlerGDSIn::ReadLayer( a2dCanvasObject* object )
1849 {
1850  if ( !ReadHeader( GDS_LAYER ) )
1851  return false;
1852 
1853  int layer;
1854  layer = ReadInt();
1855  if ( layer < 0 || layer >= wxMAXLAYER )
1856  {
1857  layer = 0;
1858  wxString mes;
1859  mes.Printf( _( "Object %s, layer >= wxMAXLAYER put on layer 0 " ), object->GetClassInfo()->GetClassName() );
1860  a2dDocviewGlobals->ReportWarningF( a2dError_NotSpecified, _( "warning GDSII file \n %s \n" ),
1861  mes.c_str() );
1862  }
1863 
1864  object->SetLayer( m_mapping[layer] );
1865  return true;
1866 }
1867 
1868 // Layer --------------------------------------------------------------------
1869 bool a2dIOHandlerGDSIn::ReadLayer( int& layer )
1870 {
1871  if ( !ReadHeader( GDS_LAYER ) )
1872  return false;
1873 
1874  layer = ReadInt();
1875  if ( layer < 0 || layer >= wxMAXLAYER )
1876  {
1877  layer = 0;
1878  wxString mes;
1879  mes.Printf( wxT( "%s" ), _( "Object layer >= wxMAXLAYER put on layer 0 " ) );
1880  a2dDocviewGlobals->ReportWarningF( a2dError_NotSpecified, _( "warning GDSII file \n %s \n" ),
1881  mes.c_str() );
1882  }
1883  return true;
1884 }
1885 
1886 // Point --------------------------------------------------------------------
1887 bool a2dIOHandlerGDSIn::Read( a2dPoint2D& Point )
1888 {
1889  FOUR_G_BYTE_SIGNED_INTEGER value;
1890  value = ReadLong();
1891  Point.m_x = value * m_doc->GetUnitsAccuracy();
1892  value = ReadLong();
1893  Point.m_y = value * m_doc->GetUnitsAccuracy();
1894  return true;
1895 }
1896 
1897 // Polygon ------------------------------------------------------------------
1898 bool a2dIOHandlerGDSIn::Read( a2dPolygonL* polygon )
1899 {
1900  if ( !ReadHeader( GDS_XY ) )
1901  return false;
1902 
1903  int points = m_recordsize / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) ) - 1;
1904 
1905  if ( points < 2 )
1906  {
1907  if ( points == 1 )
1908  {
1909  a2dPoint2D seg;
1910  Read( seg );
1912  _( "GDSII: Structure %s Only one point in Polygon: %f, %f " ), m_strucname.c_str(), seg.m_x, seg.m_y );
1913  polygon->AddPoint( seg.m_x, seg.m_y );
1914  a2dPoint2D segend;
1915  Read( segend ); // Last point matches first one read: skip
1916  }
1917  else
1918  throw GDS_Error( _( "Too few points in Polygon." ), _( "Fatal GDSII error" ) );
1919  }
1920  else
1921  {
1922  for ( int i = 0; i < points; i++ )
1923  {
1924  a2dPoint2D seg;
1925  Read( seg );
1926  polygon->AddPoint( seg.m_x, seg.m_y );
1927  }
1928  a2dPoint2D segend;
1929  Read( segend ); // Last point matches first one read: skip
1930  }
1931 
1932  return true;
1933 }
1934 
1935 // Polyline -----------------------------------------------------------------
1936 bool a2dIOHandlerGDSIn::Read( a2dVertexList* segments )
1937 {
1938  if ( !ReadHeader( GDS_XY ) )
1939  return false;
1940 
1941  int points = m_recordsize / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) );
1942  if ( points < 2 )
1943  {
1944  if ( points == 1 )
1945  {
1946  a2dLineSegment* seg = new a2dLineSegment( 0, 0 );
1947 
1948  FOUR_G_BYTE_SIGNED_INTEGER value;
1949  value = ReadLong();
1950  seg->m_x = value * m_doc->GetUnitsAccuracy();
1951  value = ReadLong();
1952  seg->m_y = value * m_doc->GetUnitsAccuracy();
1953 
1955  _( "GDSII: Structure %s Only one point in Polyline: %f, %f " ), m_strucname.c_str(), seg->m_x, seg->m_y );
1956  segments->push_back( seg );
1957  }
1958  else
1959  throw GDS_Error( _( "Too few points in Polyline." ), _( "Fatal GDSII error" ) );
1960  }
1961  else
1962  {
1963  a2dLineSegment* seg;
1964  for ( int i = 0; i < points; i++ )
1965  {
1966  seg = new a2dLineSegment( 0, 0 );
1967 
1968  FOUR_G_BYTE_SIGNED_INTEGER value;
1969  value = ReadLong();
1970  seg->m_x = value * m_doc->GetUnitsAccuracy();
1971  value = ReadLong();
1972  seg->m_y = value * m_doc->GetUnitsAccuracy();
1973  segments->push_back( seg );
1974  }
1975  }
1976 
1977  return true;
1978 }
1979 
1980 
1981 
1982 // Strans -------------------------------------------------------------------
1983 bool a2dIOHandlerGDSIn::ReadStrans( Strans& Strans )
1984 {
1985  if ( !ReadHeader( GDS_STRANS ) )
1986  return( false );
1987 
1988  EIGHT_G_BYTE_REAL real;
1989 
1990  Strans.m_stransflags.total = ReadInt();
1991 
1992  if ( ReadHeader( GDS_MAG ) )
1993  {
1994  real = ReadDouble();
1995  Strans.SetScale( real );
1996  }
1997 
1998  if ( ReadHeader( GDS_ANGLE ) )
1999  {
2000  real = ReadDouble();
2001  Strans.SetAngle( real );
2002  }
2003 
2004  return true;
2005 }
2006 
2007 
2008 // Structure ----------------------------------------------------------------
2009 bool a2dIOHandlerGDSIn::ReadStructure( a2dCanvasObject* parent )
2010 {
2011  // Grammar: BGNSTR STRNAME [STRCLASS] {<element>}*
2012  // ENDSTR
2013 
2014  if ( !ReadHeader( GDS_BGNSTR ) )
2015  return false;
2016 
2018  Structure->SetIgnoreLayer( true );
2019 
2020  //TODO store as property on current object????
2021  wxDateTime m_modificationtime = wxDateTime::Now();
2022  wxDateTime m_accesstime = wxDateTime::Now();
2023 
2024  int year;
2025  int month;
2026  int day;
2027  int hour;
2028  int minute;
2029  int second;
2030 
2031  year = ReadInt();
2032  month = ReadInt() - 1;
2033  day = ReadInt();
2034  hour = ReadInt();
2035  minute = ReadInt();
2036  second = ReadInt();
2037 
2038  m_modificationtime.Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
2039  a2dCanvasObject::PROPID_ModificationDateTime->SetPropertyToObject( Structure, m_modificationtime );
2040 
2041  year = ReadInt();
2042  month = ReadInt() - 1;
2043  day = ReadInt();
2044  hour = ReadInt();
2045  minute = ReadInt();
2046  second = ReadInt();
2047 
2048  m_accesstime.Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
2049  a2dCanvasObject::PROPID_AccessDateTime->SetPropertyToObject( Structure, m_accesstime );
2050 
2051  if ( !ReadHeader( GDS_STRNAME ) )
2052  throw GDS_Error( _( "STRNAME record missing (in Structure)" ) );
2053 
2055  Structure->SetName( m_strucname );
2056  //wxLogDebug(wxT("start structure= %s"), strucname.c_str() );
2057 
2058  if( ReadHeader( GDS_STRCLASS ) )
2059  SkipData();
2060 
2061  while ( ReadElement( Structure ) )
2062  {
2063  }
2064 
2065 
2066  if( !ReadHeader( GDS_ENDSTR ) )
2067  throw GDS_Error( _( "ENDSTR record missing (in GDSII)" ) );
2068 
2069  // Add this Element to the end of the list
2070  parent->Append( Structure );
2071  // this one needs to be resolved later
2072  GetObjectHashMap()[m_strucname] = Structure;
2073  //wxLogDebug(wxT("structure= %s"), strucname.c_str() );
2074 
2075  return true;
2076 }
2077 
2078 // Structure ----------------------------------------------------------------
2079 bool a2dIOHandlerGDSIn::ReadCameleonStructure( a2dCanvasObject* parent )
2080 {
2081  // Grammar: BGNSTR STRNAME [STRCLASS] {<element>}*
2082  // ENDSTR
2083 
2084  if ( !ReadHeader( GDS_BGNSTR ) )
2085  return false;
2086 
2088  a2dLayout* layout = new a2dLayout( cam, 0,0 );
2089  cam->AddAppearance( layout );
2090  a2dSmrtPtr<a2dDrawing> Structure = layout->GetDrawing();
2091  Structure->SetLayerSetup( m_doc->GetLayerSetup() );
2092 
2093  //TODO store as property on current object????
2094  wxDateTime m_modificationtime = wxDateTime::Now();
2095  wxDateTime m_accesstime = wxDateTime::Now();
2096 
2097  int year;
2098  int month;
2099  int day;
2100  int hour;
2101  int minute;
2102  int second;
2103 
2104  year = ReadInt();
2105  month = ReadInt() - 1;
2106  day = ReadInt();
2107  hour = ReadInt();
2108  minute = ReadInt();
2109  second = ReadInt();
2110 
2111  m_modificationtime.Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
2112  a2dCanvasObject::PROPID_ModificationDateTime->SetPropertyToObject( layout, m_modificationtime );
2113 
2114  year = ReadInt();
2115  month = ReadInt() - 1;
2116  day = ReadInt();
2117  hour = ReadInt();
2118  minute = ReadInt();
2119  second = ReadInt();
2120 
2121  m_accesstime.Set( day, ( wxDateTime::Month )month, year, hour, minute, second );
2122  a2dCanvasObject::PROPID_AccessDateTime->SetPropertyToObject( layout, m_accesstime );
2123 
2124  if ( !ReadHeader( GDS_STRNAME ) )
2125  throw GDS_Error( _( "STRNAME record missing (in Structure)" ) );
2126 
2128  cam->SetName( m_strucname );
2129  layout->SetName( m_strucname + wxT(":layout") );
2130  //wxLogDebug(wxT("start structure= %s"), strucname.c_str() );
2131 
2132  if( ReadHeader( GDS_STRCLASS ) )
2133  SkipData();
2134 
2135  while ( ReadElement( Structure->GetRootObject() ) )
2136  {
2137  }
2138 
2139 
2140  if( !ReadHeader( GDS_ENDSTR ) )
2141  throw GDS_Error( _( "ENDSTR record missing (in GDSII)" ) );
2142 
2143  // Add this Element to the end of the list
2144  cam->AddToRoot();
2145  int px = m_dx * 30 * 1.5;
2146  int py = -m_dy * 10 * 1.5;
2147  cam->SetPosXY( px, py );
2148  m_dx++;
2149  if ( m_dx > m_refMaxx )
2150  { m_dy++; m_dx =0; }
2151 
2152  // this one needs to be resolved later
2153  GetObjectHashMap()[ m_strucname ] = cam;
2154  //wxLogDebug(wxT("structure= %s"), strucname.c_str() );
2155 
2156  return true;
2157 }
2158 
2159 void a2dIOHandlerGDSIn::SetDataTypeProperty( a2dCanvasObject* toobject, wxUint16 type )
2160 {
2161  if ( type != 0 )
2163 }
2164 
2165 //----------------------------------------------------------------------------------/
2166 // a2dIOHandlerGDSOut
2167 //----------------------------------------------------------------------------------/
2168 
2169 a2dIOHandlerGDSOut::a2dIOHandlerGDSOut()
2170 {
2171  m_scale_out = 1;
2172  m_textAsPath = false;
2173  m_fromViewAsTop = false;
2174  m_asCameleons = false;
2175 }
2176 
2177 a2dIOHandlerGDSOut::~a2dIOHandlerGDSOut()
2178 {
2179 }
2180 
2181 bool a2dIOHandlerGDSOut::CanSave( const wxObject* obj )
2182 {
2183  if ( !wxDynamicCast( obj, a2dCanvasDocument ) )
2184  return false;
2185  return true;
2186 }
2187 
2189 {
2191  a2dCanvasGlobals->GetHabitat()->SetAberPolyToArc( double( a2dCanvasGlobals->GetHabitat()->GetAberPolyToArc() ) / m_doc->GetUnitsScale() );
2192 }
2193 
2195 {
2197 }
2198 
2199 bool a2dIOHandlerGDSOut::Save( a2dDocumentOutputStream& stream, const wxObject* doc )
2200 {
2201  m_doc = ( a2dCanvasDocument* ) doc;
2202  InitializeSave();
2203 
2204  a2dCanvasObject* showobject = m_doc->GetDrawing()->GetRootObject();
2205 
2206  m_layers = m_doc->GetDrawing()->GetLayerSetup();
2207 
2208  if ( m_fromViewAsTop )
2209  {
2211  if ( drawer )
2212  showobject = drawer->GetDrawingPart()->GetShowObject();
2213  }
2214 
2216  setflags.Start( showobject, false );
2217 
2218  m_mapping.resize( wxMAXLAYER );
2219 
2220  unsigned int i;
2221  for ( i = 0; i < wxMAXLAYER; i++ )
2222  m_mapping[i] = -1;
2223  for ( i = 0; i < wxMAXLAYER; i++ )
2224  if ( m_layers->GetLayerIndex()[i] != wxNullLayerInfo )
2225  m_mapping[ m_layers->GetOutMapping( i ) ] = i;
2226 
2227  for ( i = 0; i < wxMAXLAYER; i++ )
2228  if ( m_mapping[i] == -1 )
2229  m_mapping[i] = 0;
2230 
2231  m_streamo = &stream;
2232 
2233 
2234  //first check if the dat is not to big to fit in four byte integers
2235  //this is the maximum for vertexes in GDSII data
2236 
2237  a2dBoundingBox drawing = showobject->GetBbox();
2238 
2239  m_userunits_out = m_doc->GetUnitsAccuracy();
2240  if ( m_userunits_out == 0 )
2241  {
2242  wxLogWarning( wxT( "GDS userunits: 0 was set to 0.01" ) );
2243  m_userunits_out = 0.01;
2244  }
2245  drawing.SetMin( drawing.GetMinX() / m_userunits_out, drawing.GetMinY() / m_userunits_out );
2246  drawing.SetMax( drawing.GetMaxX() / m_userunits_out, drawing.GetMaxY() / m_userunits_out );
2247  a2dBoundingBox maxint( LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX );
2248 
2249  int l = 0;
2250  while ( maxint.Intersect( drawing, 0 ) != _IN )
2251  {
2252  drawing.SetMin( drawing.GetMinX() / 10.0, drawing.GetMinY() / 10.0 );
2253  drawing.SetMax( drawing.GetMaxX() / 10.0, drawing.GetMaxY() / 10.0 );
2254  l++;
2255  }
2256  m_scale_out = pow( 10., l );
2257 
2258  WriteHeader( 2, GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER, GDS_HEADER );
2259 
2260  long version;
2261  bool oke = m_doc->GetVersion().ToLong( &version );
2262  if ( oke )
2263  WriteInt( version );
2264  else
2265  WriteInt( 1 );
2266 
2267  WriteHeader( 12 * sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2268  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2269  GDS_BGNLIB );
2270 
2271  WriteInt( m_doc->GetModificationTime().GetYear() );
2272  WriteInt( m_doc->GetModificationTime().GetMonth() + 1 );
2273  WriteInt( m_doc->GetModificationTime().GetDay() );
2274  WriteInt( m_doc->GetModificationTime().GetHour() );
2275  WriteInt( m_doc->GetModificationTime().GetMinute() );
2276  WriteInt( m_doc->GetModificationTime().GetSecond() );
2277 
2278  WriteInt( m_doc->GetAccessTime().GetYear() );
2279  WriteInt( m_doc->GetAccessTime().GetMonth() + 1 );
2280  WriteInt( m_doc->GetAccessTime().GetDay() );
2281  WriteInt( m_doc->GetAccessTime().GetHour() );
2282  WriteInt( m_doc->GetAccessTime().GetMinute() );
2283  WriteInt( m_doc->GetAccessTime().GetSecond() );
2284 
2285  int value = wxStrlen( m_doc->GetLibraryName() );
2286  if ( value % 2 != 0 )
2287  value++;
2288  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_LIBNAME );
2289 
2291  WriteHeader( 2 * sizeof( EIGHT_G_BYTE_REAL ),
2292  GDSTYPE_EIGHT_G_BYTE_REAL,
2293  GDS_UNITS );
2294 
2295  WriteDouble( m_userunits_out );
2296  WriteDouble( m_doc->GetUnitsScale()*m_userunits_out * m_scale_out );
2297  a2dCanvasObjectList towrite;
2298  if ( m_doc->GetDrawing()->GetDrawingId() == a2dDrawing::sm_cameleonrefs )
2299  {
2300  if ( m_fromViewAsTop )
2301  towrite.push_back( showobject );
2302  else
2303  {
2304  a2dCanvasObjectList::iterator rootchild = m_doc->GetDrawing()->GetRootObject()->GetChildObjectList()->begin();
2305  while ( rootchild != m_doc->GetDrawing()->GetRootObject()->GetChildObjectList()->end() )
2306  {
2307  a2dCameleon* ref = wxDynamicCast( (*rootchild).Get(), a2dCameleon );
2308  if ( ref )
2309  {
2310  //a2dLayout* layout = ref->GetCameleon()->GetAppearance<a2dDiagram>();
2311  //towrite.push_back( layout->GetDrawing() );
2312  //layout->SetBin( false );
2313  towrite.push_back( ref );
2314  ref->SetBin( false );
2315  }
2316  rootchild++;
2317  }
2318  }
2319  }
2320  else
2321  {
2322  if ( m_fromViewAsTop || !m_doc->GetMultiRoot() )
2323  towrite.push_back( showobject );
2324  else
2325  {
2327  }
2328  }
2329 
2330  a2dCanvasObjectList::iterator iter = towrite.begin();
2331  while ( towrite.size() )
2332  {
2333  a2dCanvasObject* obj = *iter;
2334  SaveStructure( obj, &towrite );
2335  obj->SetBin( true );
2336  towrite.erase( iter );
2337  iter = towrite.begin();
2338  }
2339 
2340  WriteHeader( 0, 0, GDS_ENDLIB );
2341 
2342  ResetSave();
2343 
2344  return true;
2345 }
2346 
2347 void a2dIOHandlerGDSOut::SaveStructure( a2dCanvasObject* object, a2dCanvasObjectList* towrite )
2348 {
2349  SetFlags( object );
2350  if ( !object->GetRelease() )
2351  {
2352  if ( !object->GetBin() )
2353  {
2354  //write a struture BEGIN
2355 
2356  // BGNSTR
2357  WriteHeader( 12 * sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2358  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2359  GDS_BGNSTR );
2360 
2361  wxDateTime modTime = a2dCanvasObject::PROPID_ModificationDateTime->GetPropertyValue( object );
2362 
2363  WriteInt( modTime.GetYear() );
2364  WriteInt( modTime.GetMonth() + 1 );
2365  WriteInt( modTime.GetDay() );
2366  WriteInt( modTime.GetHour() );
2367  WriteInt( modTime.GetMinute() );
2368  WriteInt( modTime.GetSecond() );
2369 
2370  wxDateTime accesTime = a2dCanvasObject::PROPID_AccessDateTime->GetPropertyValue( object );
2371 
2372  WriteInt( accesTime.GetYear() );
2373  WriteInt( accesTime.GetMonth() + 1 );
2374  WriteInt( accesTime.GetDay() );
2375  WriteInt( accesTime.GetHour() );
2376  WriteInt( accesTime.GetMinute() );
2377  WriteInt( accesTime.GetSecond() );
2378 
2379  // STRNAME
2380  TWO_G_BYTE_UNSIGNED_INTEGER value = ( TWO_G_BYTE_UNSIGNED_INTEGER ) wxStrlen( object->GetName() );
2381  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_STRNAME );
2382  WriteString( object->GetName() );
2383 
2384  if ( 0 != wxDynamicCast( object, a2dCameleon ) )
2385  {
2386  a2dCameleon* cam = wxDynamicCast( object, a2dCameleon );
2387  //a2dDiagram* dia = wxDynamicCast( cam->GetAppearanceByName( cam->GetName() ), a2dDiagram );
2389  if ( dia )
2390  {
2391  a2dCanvasObjectList* childobjects = dia->GetDrawing()->GetRootObject()->GetChildObjectList();
2392  if ( childobjects != wxNullCanvasObjectList )
2393  {
2394  forEachIn( a2dCanvasObjectList, childobjects )
2395  {
2396  a2dCanvasObject* obj = *iter;
2397  if ( !obj->GetRelease() && m_layers->GetVisible( obj->GetLayer() ) || obj->GetIgnoreLayer() )
2398  {
2399  Save( obj, towrite );
2400  }
2401  }
2402  }
2403  }
2404  }
2405  else
2406  {
2407  a2dCanvasObjectList* childobjects = object->GetChildObjectList();
2408  if ( childobjects != wxNullCanvasObjectList )
2409  {
2410  forEachIn( a2dCanvasObjectList, childobjects )
2411  {
2412  a2dCanvasObject* obj = *iter;
2413  if ( !obj->GetRelease() && m_layers->GetVisible( obj->GetLayer() ) || obj->GetIgnoreLayer() )
2414  {
2415  Save( obj, towrite );
2416  }
2417  }
2418  }
2419  }
2420  WriteHeader( 0, 0, GDS_ENDSTR );
2421  }
2422  }
2423 }
2424 
2426 {
2427  if( object->IsTemporary_DontSave() )
2428  return;
2429 
2430  //in case an object can not be written as is, and need to be converted to vector paths, and written that as childs.
2432 
2433  SetFlags( object );
2434  //write the object itself as part of the structure (which is the parent )
2435  if ( 0 != wxDynamicCast( object, a2dPolylineL ) )
2436  {
2437  a2dPolylineL* obj = wxDynamicCast( object, a2dPolylineL );
2438  DoSave( obj, towrite );
2439  }
2440  else if ( 0 != wxDynamicCast( object, a2dSurface ) )
2441  {
2442  // treat surfaces without conversion to vector paths
2444  poly = wxDynamicCast( poly->Clone( a2dObject::clone_deep ), a2dSurface );
2445  if ( poly && poly->GetSegments()->HasArcs() )
2446  poly->GetSegments()->ConvertToLines();
2447 
2448  WriteBoundary( poly->GetTransformMatrix(), poly->GetSegments(), poly->GetLayer(), a2dCanvasObject::PROPID_Datatype->GetPropertyValue( poly ), poly->GetSpline() );
2449 
2450  a2dListOfa2dVertexList& holes = poly->GetHoles();
2451  if ( holes.size() )
2452  wxLogWarning( _( "a2dSurface holes are saved as polygons in contour, better convert to polygons first" ) );
2453 
2454  for( a2dListOfa2dVertexList::iterator iterp = holes.begin(); iterp != holes.end(); iterp++ )
2455  {
2456  a2dVertexListPtr vlist = ( *iterp );
2457  if ( vlist->HasArcs() )
2458  vlist->ConvertToLines();
2459 
2460  WriteBoundary( poly->GetTransformMatrix(), vlist, poly->GetLayer(), a2dCanvasObject::PROPID_Datatype->GetPropertyValue( poly ), poly->GetSpline() );
2461  }
2462  }
2463  else if ( 0 != wxDynamicCast( object, a2dPolygonL ) )
2464  {
2465  a2dPolygonL* obj = wxDynamicCast( object, a2dPolygonL );
2466  DoSave( obj, towrite );
2467  }
2468  else if ( 0 != wxDynamicCast( object, a2dVectorPath ) )
2469  {
2470  a2dVectorPath* obj = wxDynamicCast( object, a2dVectorPath );
2471  DoSave( obj, towrite );
2472  }
2473  else if ( 0 != wxDynamicCast( object, a2dCanvasObjectArrayReference ) )
2474  {
2476  DoSave( obj, towrite );
2477  }
2478  else if ( 0 != wxDynamicCast( object, a2dCanvasObjectReference ) )
2479  {
2481  DoSave( obj, towrite );
2482  }
2483  else if ( 0 != wxDynamicCast( object, a2dCameleonInst ) )
2484  {
2485  a2dCameleonInst* obj = wxDynamicCast( object, a2dCameleonInst );
2486  DoSave( obj, towrite );
2487  }
2488  else if ( 0 != wxDynamicCast( object, a2dCameleon ) )
2489  {
2490  a2dCameleon* obj = wxDynamicCast( object, a2dCameleon );
2491  DoSave( obj, towrite );
2492  }
2493  else if ( 0 != wxDynamicCast( object, a2dTextGDS ) )
2494  {
2495  a2dTextGDS* obj = wxDynamicCast( object, a2dTextGDS );
2496 
2497  if ( !m_textAsPath )
2498  DoSave( obj, towrite );
2499  else
2500  vectorpaths = obj->GetAsCanvasVpaths( false );
2501  }
2502  else if ( 0 != wxDynamicCast( object, a2dText ) )
2503  {
2504  a2dText* obj = wxDynamicCast( object, a2dText );
2505 
2506  if ( !m_textAsPath )
2507  DoSave( obj, towrite );
2508  else
2509  vectorpaths = obj->GetAsCanvasVpaths( false );
2510  }
2511  else if ( ( 0 != wxDynamicCast( object, a2dArrow ) ) ||
2512  ( 0 != wxDynamicCast( object, a2dRectC ) ) ||
2513  ( 0 != wxDynamicCast( object, a2dRect ) ) ||
2514  ( 0 != wxDynamicCast( object, a2dCircle ) ) ||
2515  ( 0 != wxDynamicCast( object, a2dEllipse ) ) ||
2516  ( 0 != wxDynamicCast( object, a2dEllipticArc ) ) ||
2517  ( 0 != wxDynamicCast( object, a2dArc ) ) ||
2518  ( 0 != wxDynamicCast( object, a2dSLine ) )
2519  )
2520  {
2521  vectorpaths = object->GetAsCanvasVpaths( false );
2522  }
2523  else if ( wxString( object->GetClassInfo()->GetClassName() ) == wxT( "a2dCanvasObject" ) )
2524  {
2525  WriteHeader( 0, 0, GDS_SREF );
2526  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2527  GDSTYPE_BIT_ARRAY,
2528  GDS_ELFLAGS );
2529 
2530  WriteInt( m_objectFlags );
2531 
2532  int value = wxStrlen( object->GetName() );
2533  if ( value % 2 != 0 )
2534  value++;
2535  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_SNAME );
2536  WriteString( object->GetName() );
2537 
2538  //write a structure reference in the parent object
2539  a2dAffineMatrix lworld = object->GetTransformMatrix();
2540  if ( !lworld.IsIdentity() )
2541  {
2542  Strans* strans = new Strans();
2543  strans->MakeStrans( lworld );
2544  if ( strans->GetStrans() )
2545  Write( strans );
2546  }
2547 
2548  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2549  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2550  GDS_XY );
2551 
2552  WritePoint( object->GetPosX(), object->GetPosY() );
2553 
2554  WriteHeader( 0, 0, GDS_ENDEL );
2555  towrite->push_back( object );
2556  }
2557  else
2558  {
2559  wxLogWarning( wxT( "GDSIO : object %s is not implemented for output" ), object->GetClassInfo()->GetClassName() );
2560  }
2561 
2562  //now write extra vector paths ( e.g. as a result of a converted object )
2563  if ( vectorpaths != wxNullCanvasObjectList )
2564  {
2565  a2dAffineMatrix lworld = object->GetTransformMatrix();
2566 
2567  for( a2dCanvasObjectList::iterator iter = vectorpaths->begin(); iter != vectorpaths->end(); ++iter )
2568  {
2569  a2dVectorPath* canpath = ( a2dVectorPath* ) ( *iter ).Get();
2570  WriteVpath( lworld, canpath->GetSegments(), canpath->GetLayer(), canpath->GetDataType(), canpath->GetPathType(), canpath->GetContourWidth() );
2571  }
2572  delete vectorpaths;
2573  }
2574 
2575  if ( object->GetChildObjectList() != wxNullCanvasObjectList && object->GetChildObjectsCount() )
2576  {
2577  WriteHeader( 0, 0, GDS_SREF );
2578  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2579  GDSTYPE_BIT_ARRAY,
2580  GDS_ELFLAGS );
2581 
2582  WriteInt( m_objectFlags );
2583 
2584  int value = wxStrlen( object->GetName() );
2585  if ( value % 2 != 0 )
2586  value++;
2587  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_SNAME );
2588  WriteString( object->GetName() );
2589 
2590  //write a structure reference in the parent object
2591  a2dAffineMatrix lworld = object->GetTransformMatrix();
2592  if ( !lworld.IsIdentity() )
2593  {
2594  Strans* strans = new Strans();
2595  strans->MakeStrans( lworld );
2596  if ( strans->GetStrans() )
2597  Write( strans );
2598  }
2599 
2600  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2601  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2602  GDS_XY );
2603 
2604  WritePoint( object->GetPosX(), object->GetPosY() );
2605 
2606  WriteHeader( 0, 0, GDS_ENDEL );
2607 
2608  //a new structure is needed
2609  towrite->push_back( object );
2610  }
2611 
2612 }
2613 
2614 void a2dIOHandlerGDSOut::DoSave( a2dPolylineL* obj, a2dCanvasObjectList* WXUNUSED( towrite ) )
2615 {
2616  a2dVertexList* origpoints = obj->GetSegments();
2617 
2618  a2dVertexList* rlist;
2619  if ( obj->GetSpline() || origpoints->HasArcs() )
2620  {
2621 
2622  a2dVertexList* lpoints = new a2dVertexList();
2623  *lpoints = *origpoints;
2624  lpoints->ConvertSplinedPolyline( 10 );
2625  rlist = lpoints;
2626  }
2627  else
2628  rlist = origpoints;
2629 
2630  WritePath( obj->GetTransformMatrix(), rlist, obj->GetLayer(),
2632 
2633  /*
2634  double xscale = obj->GetEndScaleX();
2635  double yscale = obj->GetEndScaleY();
2636 
2637  if ( obj->GetBegin() )
2638  {
2639  a2dVertexList::compatibility_iterator node = rlist->GetFirst();
2640  a2dPoint2D* point1 = (a2dPoint2D*)node->GetData();
2641  node = node->GetNext();
2642  a2dPoint2D* point2 = (a2dPoint2D*)node->GetData();
2643 
2644  double dx, dy;
2645  dx=point2->m_x-point1->m_x;
2646  dy=point2->m_y-point1->m_y;
2647 
2648  double ang1;
2649  if (!dx && !dy)
2650  ang1=0;
2651  else
2652  ang1 = wxRadToDeg(atan2(dy,dx));
2653 
2654  a2dAffineMatrix lworld;
2655  //clockwise rotation so minus
2656  lworld.Scale(xscale,yscale,0,0);
2657  lworld.Rotate(-ang1);
2658  lworld.Translate(point1->m_x,point1->m_y);
2659 
2660  WriteStartElementAttributes( "g" );
2661  s.Printf ( "matrix( %f %f %f %f %f %f )",
2662  lworld.GetValue(0,0), lworld.GetValue(0,1),
2663  lworld.GetValue(1,0), lworld.GetValue(1,1),
2664  lworld.GetValue(2,0), lworld.GetValue(2,1)
2665  );
2666  WriteAttribute( "transform", s );
2667  WriteEndAttributes();
2668 
2669  Save( obj->GetBegin(), layer );
2670 
2671  WriteEndElement();
2672  }
2673 
2674  if ( obj->GetEnd() )
2675  {
2676  a2dVertexList::compatibility_iterator node = rlist->GetLast();
2677  a2dPoint2D* point1 = (a2dPoint2D*)node->GetData();
2678  node = node->GetPrevious();
2679  a2dPoint2D* point2 = (a2dPoint2D*)node->GetData();
2680 
2681  double dx, dy;
2682  dx=point2->m_x-point1->m_x;
2683  dy=point2->m_y-point1->m_y;
2684  double ang2;
2685  if (!dx && !dy)
2686  ang2=0;
2687  else
2688  ang2 = wxRadToDeg(atan2(dy,dx));
2689 
2690  a2dAffineMatrix lworld;
2691  //clockwise rotation so minus
2692  lworld.Scale(xscale,yscale,0,0);
2693  lworld.Rotate(-ang2);
2694  lworld.Translate(point1->m_x,point1->m_y);
2695 
2696  WriteStartElementAttributes( "g" );
2697  s.Printf ( "matrix( %f %f %f %f %f %f )",
2698  lworld.GetValue(0,0), lworld.GetValue(0,1),
2699  lworld.GetValue(1,0), lworld.GetValue(1,1),
2700  lworld.GetValue(2,0), lworld.GetValue(2,1)
2701  );
2702  WriteAttribute( "transform", s );
2703  WriteEndAttributes();
2704 
2705  Save( obj->GetEnd(), layer );
2706 
2707  WriteEndElement();
2708  }
2709  */
2710  if ( obj->GetSpline() || origpoints->HasArcs() )
2711  delete rlist;
2712 }
2713 
2714 void a2dIOHandlerGDSOut::DoSave( a2dPolygonL* obj, a2dCanvasObjectList* WXUNUSED( towrite ) )
2715 {
2716  WriteBoundary( obj->GetTransformMatrix(), obj->GetSegments(), obj->GetLayer(), a2dCanvasObject::PROPID_Datatype->GetPropertyValue( obj ), obj->GetSpline() );
2717 }
2718 
2719 void a2dIOHandlerGDSOut::DoSave( a2dVectorPath* obj, a2dCanvasObjectList* WXUNUSED( towrite ) )
2720 {
2721  WriteVpath( obj->GetTransformMatrix(), obj->GetSegments(), obj->GetLayer(), a2dCanvasObject::PROPID_Datatype->GetPropertyValue( obj ), obj->GetPathType(), obj->GetContourWidth() );
2722 }
2723 
2724 void a2dIOHandlerGDSOut::DoSave( a2dText* obj, a2dCanvasObjectList* WXUNUSED( towrite ) )
2725 {
2726  WriteHeader( 0, 0, GDS_TEXT );
2727  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2728  GDSTYPE_BIT_ARRAY,
2729  GDS_ELFLAGS );
2730 
2731  WriteInt( m_objectFlags );
2732 
2733  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2734  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2735  GDS_LAYER );
2736 
2737  WriteInt( m_mapping[obj->GetLayer()] );
2738 
2739  // Texttype
2740  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2741  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2742  GDS_TEXTTYPE );
2743 
2744  WriteInt( TEXT_PATH_END_SQAURE );
2745 
2746  /* for the moment this is in the strans together with matrix
2747  if ( obj->GetTextHeight() != 0 )
2748  {
2749  WriteHeader(sizeof(FOUR_G_BYTE_SIGNED_INTEGER),
2750  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2751  GDS_WIDTH);
2752  WriteLong( (int) (obj->GetTextHeight() / m_userunits_out/m_scale_out) );
2753  }
2754  */
2755 
2756  a2dAffineMatrix lworld = obj->GetTransformMatrix();
2757  if ( !lworld.IsIdentity() )
2758  {
2759  Strans strans = Strans();
2760  strans.MakeStrans( lworld );
2761  if( obj->GetTextHeight() != 0 )
2762  strans.SetScale( strans.GetScale() * obj->GetTextHeight() );
2763 
2764  if ( strans.GetStrans() )
2765  Write( &strans );
2766  }
2767 
2768  // write the coordinate to the outputstream
2769  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2770  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2771  GDS_XY );
2772 
2773  WritePoint( obj->GetPosX(), obj->GetPosY() );
2774 
2775  // writes the text
2776  int nrChar = wxStrlen( obj->GetText() );
2777  if ( nrChar % 2 != 0 )
2778  nrChar++;
2779  WriteHeader( nrChar, GDSTYPE_ASCII_STRING, GDS_STRING );
2780 
2781  WriteString( obj->GetText() );
2782 
2783  WriteHeader( 0, 0, GDS_ENDEL );
2784 }
2785 
2786 void a2dIOHandlerGDSOut::DoSave( a2dTextGDS* obj, a2dCanvasObjectList* WXUNUSED( towrite ) )
2787 {
2788  WriteHeader( 0, 0, GDS_TEXT );
2789 
2790  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2791  GDSTYPE_BIT_ARRAY,
2792  GDS_ELFLAGS );
2793 
2794  WriteInt( m_objectFlags );
2795 
2796  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2797  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2798  GDS_LAYER );
2799 
2800  WriteInt( m_mapping[obj->GetLayer()] );
2801 
2802  // Texttype
2803  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2804  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2805  GDS_TEXTTYPE );
2806 
2807  WriteInt( obj->GetTextType() );
2808 
2809  if ( obj->GetPresentationFlags() )
2810  {
2811  // write only when a_presentation isn't default
2812  if ( ( obj->GetFontGDS() != DEFAULT_PRESENTATION_FONT ) ||
2813  ( obj->GetVertical() != DEFAULT_PRESENTATION_VERTICAL ) ||
2814  ( obj->GetHorizontal() != DEFAULT_PRESENTATION_HORIZONTAL ) )
2815  {
2816  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2817  GDSTYPE_BIT_ARRAY,
2818  GDS_PRESENTATION );
2819  WriteInt( obj->GetPresentationFlags() );
2820  }
2821  }
2822 
2823  if ( obj->GetPathtype() )
2824  {
2825  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2826  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2827  GDS_PATHTYPE );
2828 
2829  WriteInt( obj->GetPathtype() );
2830  }
2831 
2832  /* for the moment this is in the strans together with matrix
2833  if ( obj->GetTextHeight() != 0 )
2834  {
2835  WriteHeader(sizeof(FOUR_G_BYTE_SIGNED_INTEGER),
2836  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2837  GDS_WIDTH);
2838  WriteLong( (int) (obj->GetTextHeight() / m_userunits_out/m_scale_out) );
2839  }
2840  */
2841 
2842  a2dAffineMatrix lworld = obj->GetTransformMatrix();
2843  if ( !lworld.IsIdentity() )
2844  {
2845  Strans strans = Strans();
2846  strans.MakeStrans( lworld );
2847  if( obj->GetTextHeight() != 0 )
2848  strans.SetScale( strans.GetScale() * obj->GetTextHeight() / a2dTextGDS::GetFontScaleFactor() );
2849 
2850  if ( strans.GetStrans() )
2851  Write( &strans );
2852  }
2853 
2854  // write the coordinate to the outputstream
2855  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2856  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2857  GDS_XY );
2858 
2859  WritePoint( obj->GetPosX(), obj->GetPosY() );
2860 
2861  // writes the text
2862  int nrChar = wxStrlen( obj->GetText() );
2863  if ( nrChar % 2 != 0 )
2864  nrChar++;
2865  WriteHeader( nrChar, GDSTYPE_ASCII_STRING, GDS_STRING );
2866 
2867  WriteString( obj->GetText() );
2868 
2869  WriteHeader( 0, 0, GDS_ENDEL );
2870 }
2871 
2872 void a2dIOHandlerGDSOut::DoSave( a2dCanvasObjectReference* obj, a2dCanvasObjectList* towrite )
2873 {
2874  WriteHeader( 0, 0, GDS_SREF );
2875  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2876  GDSTYPE_BIT_ARRAY,
2877  GDS_ELFLAGS );
2878 
2879  WriteInt( m_objectFlags );
2880 
2881  int value = wxStrlen( obj->GetName() );
2882  if ( value % 2 != 0 )
2883  value++;
2884  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_SNAME );
2885  WriteString( obj->GetName() );
2886 
2887  //write a structure reference in the parent object
2888  a2dAffineMatrix lworld = obj->GetTransformMatrix();
2889  if ( !lworld.IsIdentity() )
2890  {
2891  Strans* strans = new Strans();
2892  strans->MakeStrans( lworld );
2893  if ( strans->GetStrans() )
2894  Write( strans );
2895  }
2896 
2897  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2898  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2899  GDS_XY );
2900 
2901  WritePoint( obj->GetPosX(), obj->GetPosY() );
2902 
2903  WriteHeader( 0, 0, GDS_ENDEL );
2904 
2905  if ( obj->GetCanvasObject() )
2906  towrite->push_back( obj->GetCanvasObject() );
2907 }
2908 
2909 void a2dIOHandlerGDSOut::DoSave( a2dCanvasObjectArrayReference* obj, a2dCanvasObjectList* towrite )
2910 {
2911  WriteHeader( 0, 0, GDS_AREF );
2912  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2913  GDSTYPE_BIT_ARRAY,
2914  GDS_ELFLAGS );
2915 
2916  WriteInt( m_objectFlags );
2917 
2918  int value = wxStrlen( obj->GetName() );
2919  if ( value % 2 != 0 )
2920  value++;
2921  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_SNAME );
2922  WriteString( obj->GetName() );
2923 
2924  //write a structure reference in the parent object
2925  a2dAffineMatrix lworld = obj->GetTransformMatrix();
2926  if ( !lworld.IsIdentity() )
2927  {
2928  Strans* strans = new Strans();
2929  strans->MakeStrans( lworld );
2930  if ( strans->GetStrans() )
2931  Write( strans );
2932  }
2933 
2934  WriteHeader( 2 * sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2935  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
2936  GDS_COLROW );
2937 
2938  WriteInt( obj->GetColumns() );
2939  WriteInt( obj->GetRows() );
2940 
2941  WriteHeader( 6 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2942  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2943  GDS_XY );
2944 
2945  WritePoint( obj->GetPosX(), obj->GetPosY() );
2946 
2947  WritePoint( obj->GetPosX() + obj->GetHorzSpace() * obj->GetColumns(), obj->GetPosY() );
2948  WritePoint( obj->GetPosX(), obj->GetPosY() + obj->GetVertSpace() * obj->GetRows() );
2949 
2950  WriteHeader( 0, 0, GDS_ENDEL );
2951 
2952  if ( obj->GetCanvasObject() )
2953  towrite->push_back( obj->GetCanvasObject() );
2954 }
2955 
2956 void a2dIOHandlerGDSOut::DoSave( a2dCameleonInst* obj, a2dCanvasObjectList* towrite )
2957 {
2959  if ( ! dia )
2960  return;
2961 
2962  WriteHeader( 0, 0, GDS_SREF );
2963  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
2964  GDSTYPE_BIT_ARRAY,
2965  GDS_ELFLAGS );
2966 
2967  WriteInt( m_objectFlags );
2968 
2969  int value = wxStrlen( dia->GetCameleon()->GetName() );
2970  if ( value % 2 != 0 )
2971  value++;
2972  WriteHeader( value, GDSTYPE_ASCII_STRING, GDS_SNAME );
2973  WriteString( dia->GetCameleon()->GetName() );
2974 
2975  //write a structure reference in the parent object
2976  a2dAffineMatrix lworld = obj->GetTransformMatrix();
2977  if ( !lworld.IsIdentity() )
2978  {
2979  Strans* strans = new Strans();
2980  strans->MakeStrans( lworld );
2981  if ( strans->GetStrans() )
2982  Write( strans );
2983  }
2984 
2985  WriteHeader( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
2986  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
2987  GDS_XY );
2988 
2989  WritePoint( obj->GetPosX(), obj->GetPosY() );
2990 
2991  WriteHeader( 0, 0, GDS_ENDEL );
2992 
2993  if ( m_asCameleons && dia->GetCameleon() )
2994  towrite->push_back( dia->GetCameleon() );
2995 }
2996 
2997 void a2dIOHandlerGDSOut::DoSave( a2dCameleon* obj, a2dCanvasObjectList* towrite )
2998 {
2999  //SaveStructure( obj, towrite );
3000 }
3001 
3002 void a2dIOHandlerGDSOut::Write( Strans* Strans )
3003 {
3004  // writes only when strans isn't default
3005  if ( ( Strans->m_stransflags.bits.abs_angle != DEFAULT_STRANS_ABS_ANGLE ) ||
3006  ( Strans->m_stransflags.bits.abs_scale != DEFAULT_STRANS_ABS_SCALE ) ||
3007  ( Strans->m_stransflags.bits.reflection != DEFAULT_STRANS_REFLECTION ) ||
3008  ( Strans->GetScale() != DEFAULT_STRANS_SCALE ) ||
3009  ( Strans->GetAngle() != DEFAULT_STRANS_ANGLE ) )
3010  {
3011  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3012  GDSTYPE_BIT_ARRAY,
3013  GDS_STRANS );
3014  WriteInt( Strans->m_stransflags.total );
3015 
3016  // writes only the scale when different from default
3017  if ( Strans->GetScale() != DEFAULT_STRANS_SCALE )
3018  {
3019  WriteHeader( sizeof( EIGHT_G_BYTE_REAL ),
3020  GDSTYPE_EIGHT_G_BYTE_REAL,
3021  GDS_MAG );
3022  WriteDouble( Strans->GetScale() );
3023 
3024  }
3025 
3026  // writes only the angle when different from default
3027  if ( Strans->GetAngle() != DEFAULT_STRANS_ANGLE )
3028  {
3029  WriteHeader( sizeof( EIGHT_G_BYTE_REAL ),
3030  GDSTYPE_EIGHT_G_BYTE_REAL,
3031  GDS_ANGLE );
3032  WriteDouble( Strans->GetAngle() );
3033  }
3034  }
3035 }
3036 
3037 void a2dIOHandlerGDSOut::WriteHeader( TWO_G_BYTE_UNSIGNED_INTEGER nw_recordsize, G_BYTE nw_datatype, G_BYTE nw_recordtype )
3038 {
3039  // a string must be odd length
3040  if ( nw_datatype == GDSTYPE_ASCII_STRING &&
3041  ( nw_recordsize % 2 ) != 0 )
3042  nw_recordsize++;
3043 
3044  WriteInt( nw_recordsize + GDS_HEADERSIZE );
3045  WriteByte( nw_recordtype );
3046  WriteByte( nw_datatype );
3047 
3048  m_recordsize = ( TWO_G_BYTE_UNSIGNED_INTEGER ) nw_recordsize;
3049 }
3050 
3051 
3052 
3053 void a2dIOHandlerGDSOut::WriteString( const wxString& a_string )
3054 {
3055  int value = a_string.Len();
3056  for ( int i = 0 ; i < value; i++ )
3057  WriteByte( a_string[i] );
3058 
3059  if ( value % 2 != 0 )
3060  WriteByte( wxT( '\0' ) );
3061 }
3062 
3063 
3064 // Elflags ------------------------------------------------------------------
3065 void a2dIOHandlerGDSOut::SetFlags( a2dCanvasObject* Element )
3066 {
3067  if ( ( Element->GetTemplate() != 0 ) ||
3068  ( Element->GetExternal() != 0 ) )
3069  {
3070  m_objectFlags = 0;
3071 
3072  if ( Element->GetTemplate() )
3073  m_objectFlags += 1 << 1;
3074 
3075  if ( Element->GetExternal() )
3076  m_objectFlags += 1 << 2;
3077  }
3078 }
3079 
3080 // Point --------------------------------------------------------------------
3081 void a2dIOHandlerGDSOut::WritePoint( double xi, double yi )
3082 {
3083  long x;
3084  long y;
3085  if ( xi > 0 )
3086  x = ( long ) ( xi / m_userunits_out / m_scale_out + 0.5 );
3087  else
3088  x = ( long ) ( xi / m_userunits_out / m_scale_out - 0.5 );
3089  if ( yi > 0 )
3090  y = ( long ) ( yi / m_userunits_out / m_scale_out + 0.5 );
3091  else
3092  y = ( long ) ( yi / m_userunits_out / m_scale_out - 0.5 );
3093 
3094  WriteLong( x );
3095  WriteLong( y );
3096 }
3097 
3098 void a2dIOHandlerGDSOut::WriteVpath( const a2dAffineMatrix& lworld, const a2dVpath* path, int layer, int datatype, int pathtype, double width )
3099 {
3100  double tstep = 1 / ( double ) SPLINE_STEP;
3101  unsigned int i;
3102 
3103  a2dVertexArray* cpoints = new a2dVertexArray;
3104 
3105  double x, y;
3106  bool move = false;
3107  int count = 0;
3108  bool nostrokeparts = false;
3109 
3110  //first draw as much as possible ( nostroke parts may stop this first round )
3111  for ( i = 0; i < path->size(); i++ )
3112  {
3113  a2dVpathSegment* seg = path->Item( i );
3114  switch ( seg->GetType() )
3115  {
3116  case a2dPATHSEG_MOVETO:
3117  if ( count == 0 )
3118  {
3119  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3120  cpoints->push_back( new a2dLineSegment( x, y ) );
3121  count++;
3122  }
3123  else
3124  {
3125  i--;
3126  move = true;
3127  }
3128  break;
3129 
3130  case a2dPATHSEG_LINETO:
3131  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3132  cpoints->push_back( new a2dLineSegment( x, y ) );
3133  count++;
3134  break;
3136  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3137  cpoints->push_back( new a2dLineSegment( x, y ) );
3138  count++;
3139  nostrokeparts = true;
3140  break;
3141 
3143  nostrokeparts = true;
3144  case a2dPATHSEG_CBCURVETO:
3145  {
3146  double xw, yw;
3147 
3148  double xwl = path->Item( i ? i - 1 : 0 )->m_x1;
3149  double ywl = path->Item( i ? i - 1 : 0 )->m_y1;
3151 
3152  int step;
3153  double t = 0;
3154  for ( step = 0; step <= SPLINE_STEP; step++ )
3155  {
3156  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
3157  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
3158  lworld.TransformPoint( xw, yw, x, y );
3159  cpoints->push_back( new a2dLineSegment( x, y ) );
3160  count++;
3161  t = t + tstep;
3162  }
3163  }
3164  break;
3165 
3167  nostrokeparts = true;
3168  case a2dPATHSEG_QBCURVETO:
3169  {
3170  double xw, yw;
3171 
3172  double xwl = path->Item( i ? i - 1 : 0 )->m_x1;
3173  double ywl = path->Item( i ? i - 1 : 0 )->m_y1;
3175 
3176  int step;
3177  double t = 0;
3178  for ( step = 0; step <= SPLINE_STEP; step++ )
3179  {
3180  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
3181  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
3182  lworld.TransformPoint( xw, yw, x, y );
3183  cpoints->push_back( new a2dLineSegment( x, y ) );
3184  count++;
3185  t = t + tstep;
3186  }
3187  }
3188  break;
3189 
3191  nostrokeparts = true;
3192  case a2dPATHSEG_ARCTO:
3193  {
3194  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg;
3195 
3196  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
3197 
3198  if ( cseg->CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
3199  {
3200  double dphi;
3201  unsigned int segments;
3202  a2dGlobals->Aberration( phit, radius , dphi, segments );
3203 
3204  double theta = beginrad;
3205  unsigned int step;
3206 
3207  for ( step = 0; step < segments + 1; step++ )
3208  {
3209  lworld.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
3210  cpoints->push_back( new a2dLineSegment( x, y ) );
3211  count++;
3212  theta = theta + dphi;
3213  }
3214  }
3215  else
3216  {
3217  lworld.TransformPoint( cseg->m_x1, cseg->m_y1, x, y );
3218  cpoints->push_back( new a2dLineSegment( x, y ) );
3219  count++;
3220  }
3221  }
3222  break;
3223  }
3224 
3225  if ( move )
3226  {
3227  WritePath( a2dIDENTITY_MATRIX, cpoints, layer, datatype, pathtype, width );
3228  move = false;
3229  cpoints->clear();
3230  count = 0;
3231  }
3232  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
3233  {
3234  if ( nostrokeparts || seg->GetClose() == a2dPATHSEG_END_CLOSED_NOSTROKE )
3235  {
3236  WriteBoundary( a2dIDENTITY_MATRIX, cpoints, layer, datatype );
3237  nostrokeparts = true;
3238  }
3239  else
3240  {
3241  WriteBoundary( a2dIDENTITY_MATRIX, cpoints, layer, datatype );
3242  }
3243 
3244  move = false;
3245  cpoints->clear();
3246  count = 0;
3247  }
3248  else if ( i == path->size() - 1 ) //last segment?
3249  {
3250  WritePath( a2dIDENTITY_MATRIX, cpoints, layer, datatype, pathtype, width );
3251  cpoints->clear();
3252  }
3253  }
3254 
3255  if ( nostrokeparts )
3256  {
3257  move = false;
3258  count = 0;
3259  cpoints->clear();
3260 
3261  nostrokeparts = false;
3262 
3263  double lastmovex = 0;
3264  double lastmovey = 0;
3265 
3266  for ( i = 0; i < path->size(); i++ )
3267  {
3268  a2dVpathSegment* seg = path->Item( i );
3269  switch ( seg->GetType() )
3270  {
3271  case a2dPATHSEG_MOVETO:
3272  if ( count == 0 )
3273  {
3274  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3275  cpoints->push_back( new a2dLineSegment( x, y ) );
3276  lastmovex = x;
3277  lastmovey = y;
3278  count++;
3279  }
3280  else
3281  {
3282  i--;
3283  move = true;
3284  }
3285  break;
3286 
3287  case a2dPATHSEG_LINETO:
3288  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3289  cpoints->push_back( new a2dLineSegment( x, y ) );
3290  count++;
3291  break;
3292 
3297  if ( count == 0 )
3298  {
3299  lworld.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3300  cpoints->push_back( new a2dLineSegment( x, y ) );
3301  count++;
3302  }
3303  else
3304  {
3305  i--;
3306  nostrokeparts = true;
3307  }
3308  break;
3309 
3310  case a2dPATHSEG_CBCURVETO:
3311  {
3312  double xw, yw;
3313 
3314  double xwl = path->Item( i ? i - 1 : 0 )->m_x1;
3315  double ywl = path->Item( i ? i - 1 : 0 )->m_y1;
3317 
3318  int step;
3319  double t = 0;
3320  for ( step = 0; step <= SPLINE_STEP; step++ )
3321  {
3322  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
3323  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
3324  lworld.TransformPoint( xw, yw, x, y );
3325  cpoints->push_back( new a2dLineSegment( x, y ) );
3326  count++;
3327  t = t + tstep;
3328  }
3329  }
3330  break;
3331 
3332  case a2dPATHSEG_QBCURVETO:
3333  {
3334  double xw, yw;
3335 
3336  double xwl = path->Item( i ? i - 1 : 0 )->m_x1;
3337  double ywl = path->Item( i ? i - 1 : 0 )->m_y1;
3339 
3340  int step;
3341  double t = 0;
3342  for ( step = 0; step <= SPLINE_STEP; step++ )
3343  {
3344  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
3345  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
3346  lworld.TransformPoint( xw, yw, x, y );
3347  cpoints->push_back( new a2dLineSegment( x, y ) );
3348  count++;
3349  t = t + tstep;
3350  }
3351  }
3352  break;
3353 
3354  case a2dPATHSEG_ARCTO:
3355  {
3356  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg;
3357 
3358  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
3359 
3360  if ( cseg->CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
3361  {
3362  double dphi;
3363  unsigned int segments;
3364  a2dGlobals->Aberration( phit, radius , dphi, segments );
3365 
3366  double theta = beginrad;
3367  unsigned int step;
3368 
3369  double x, y;
3370  for ( step = 0; step < segments + 1; step++ )
3371  {
3372  lworld.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
3373  cpoints->push_back( new a2dLineSegment( x, y ) );
3374  count++;
3375  theta = theta + dphi;
3376  }
3377  }
3378  else
3379  {
3380  double x, y;
3381  lworld.TransformPoint( cseg->m_x1, cseg->m_y1, x, y );
3382  cpoints->push_back( new a2dLineSegment( x, y ) );
3383  count++;
3384  }
3385  }
3386  break;
3387  }
3388 
3389  if ( move || nostrokeparts )
3390  {
3391  WritePath( a2dIDENTITY_MATRIX, cpoints, layer, datatype, pathtype, width );
3392  move = false;
3393  nostrokeparts = false;
3394  cpoints->clear();
3395  count = 0;
3396  }
3397  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
3398  {
3399  if ( seg->GetClose() == a2dPATHSEG_END_CLOSED )
3400  {
3401  cpoints->push_back( new a2dLineSegment( lastmovex, lastmovey ) );
3402  count++;
3403  }
3404  WritePath( a2dIDENTITY_MATRIX, cpoints, layer, datatype, pathtype, width );
3405  nostrokeparts = false;
3406  move = false;
3407  cpoints->clear();
3408  count = 0;
3409  }
3410  else if ( i == path->size() )
3411  {
3412  WritePath( a2dIDENTITY_MATRIX, cpoints, layer, datatype, pathtype, width );
3413  cpoints->clear();
3414  }
3415  }
3416  }
3417 
3418  delete cpoints;
3419 
3420 }
3421 
3422 // Path ---------------------------------------------------------------------
3423 void a2dIOHandlerGDSOut::WritePath( const a2dAffineMatrix& lworld, a2dVertexArray* points, int layer, int datatype, int pathtype, double width )
3424 {
3425  WriteHeader( 0, 0, GDS_PATH );
3426 
3427  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3428  GDSTYPE_BIT_ARRAY,
3429  GDS_ELFLAGS );
3430 
3431  WriteInt( m_objectFlags );
3432 
3433  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3434  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3435  GDS_LAYER );
3436 
3437  WriteInt( m_mapping[layer] );
3438 
3439  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3440  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3441  GDS_DATATYPE );
3442 
3443  WriteInt( datatype );
3444 
3445  if ( pathtype )
3446  {
3447  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3448  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3449  GDS_PATHTYPE );
3450 
3451  WriteInt( pathtype );
3452  }
3453 
3454  if ( width )
3455  {
3456  WriteHeader( sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
3457  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
3458  GDS_WIDTH );
3459  WriteLong( Round( width / m_userunits_out / m_scale_out ) );
3460  }
3461 
3462  long help;
3463  points->ConvertToLines();
3464  unsigned int n;
3465  n = points->size();
3466 
3467  help = 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) * n;
3468 
3469  if ( help > 65530L )
3470  {
3471  wxLogWarning( wxT( "%s" ), _( "to many points in Polyline" ) );
3472  help = 65530L;
3473  n = help / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) );
3474  }
3475  WriteHeader( help, GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER, GDS_XY );
3476 
3477  unsigned int i;
3478  for ( i = 0; i < n; i++ )
3479  {
3480  double x, y;
3481  lworld.TransformPoint( points->Item( i )->m_x, points->Item( i )->m_y, x, y );
3482  WritePoint( x, y );
3483  }
3484 
3485  WriteHeader( 0, 0, GDS_ENDEL );
3486 }
3487 
3488 // Path ---------------------------------------------------------------------
3489 void a2dIOHandlerGDSOut::WritePath( const a2dAffineMatrix& lworld, a2dVertexList* points, int layer, int datatype, int pathtype, double width )
3490 {
3491  WriteHeader( 0, 0, GDS_PATH );
3492 
3493  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3494  GDSTYPE_BIT_ARRAY,
3495  GDS_ELFLAGS );
3496 
3497  WriteInt( m_objectFlags );
3498 
3499  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3500  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3501  GDS_LAYER );
3502 
3503  WriteInt( m_mapping[layer] );
3504 
3505  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3506  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3507  GDS_DATATYPE );
3508 
3509  WriteInt( datatype );
3510 
3511  if ( pathtype )
3512  {
3513  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3514  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3515  GDS_PATHTYPE );
3516 
3517  WriteInt( pathtype );
3518  }
3519 
3520  if ( width )
3521  {
3522  WriteHeader( sizeof( FOUR_G_BYTE_SIGNED_INTEGER ),
3523  GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER,
3524  GDS_WIDTH );
3525  WriteLong( Round( width / m_userunits_out / m_scale_out ) );
3526  }
3527 
3528  points->ConvertToLines();
3529  unsigned int n = points->size();
3530 
3531  long help = 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) * n;
3532  if ( help > 65530L )
3533  {
3534  wxLogWarning( wxT( "%s" ), _( "to many points in Polyline" ) );
3535  help = 65530L;
3536  n = help / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) );
3537  }
3538  WriteHeader( help, GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER, GDS_XY );
3539 
3540  a2dVertexList::iterator iter = points->begin();
3541  unsigned int i = 0;
3542  while ( i < n )
3543  {
3544  a2dPoint2D point = ( *iter )->GetPoint();
3545  double x, y;
3546  lworld.TransformPoint( point.m_x, point.m_y, x, y );
3547  WritePoint( x, y );
3548  iter++;
3549  i++;
3550  }
3551 
3552  WriteHeader( 0, 0, GDS_ENDEL );
3553 }
3554 
3555 // Boundary------------------------------------------------------------------
3556 void a2dIOHandlerGDSOut::WriteBoundary( const a2dAffineMatrix& lworld, a2dVertexArray* points, int layer, int datatype )
3557 {
3558  WriteHeader( 0, 0, GDS_BOUNDARY );
3559 
3560  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3561  GDSTYPE_BIT_ARRAY,
3562  GDS_ELFLAGS );
3563 
3564  WriteInt( m_objectFlags );
3565 
3566  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3567  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3568  GDS_LAYER );
3569 
3570  WriteInt( m_mapping[layer] );
3571 
3572  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3573  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3574  GDS_DATATYPE );
3575 
3576  WriteInt( datatype );
3577 
3578  points->ConvertToLines();
3579  long help;
3580  unsigned int n = points->size();
3581 
3582  help = 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) * ( n + 1 );
3583 
3584  if ( help > 65530L )
3585  {
3586  wxLogWarning( wxT( "%s" ), _( "to many points in Polyline" ) );
3587  //clip the number of point to write to the max possible.
3588  //TODO use boolean algorithms to divide big polygons.
3589  help = 65530L;
3590  n = help / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) ) - 1;
3591  }
3592  WriteHeader( help, GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER, GDS_XY );
3593 
3594  double x, y;
3595  unsigned int i;
3596  for ( i = 0; i < n; i++ )
3597  {
3598  lworld.TransformPoint( points->Item( i )->m_x, points->Item( i )->m_y, x, y );
3599  WritePoint( x, y );
3600  }
3601  lworld.TransformPoint( points->Item( 0 )->m_x, points->Item( 0 )->m_y, x, y );
3602  WritePoint( x, y );
3603 
3604  WriteHeader( 0, 0, GDS_ENDEL );
3605 }
3606 
3607 // Boundary------------------------------------------------------------------
3608 void a2dIOHandlerGDSOut::WriteBoundary( const a2dAffineMatrix& lworld, a2dVertexList* points, int layer, int datatype, bool spline )
3609 {
3610  a2dVertexList* rlist;
3611 
3612  if ( spline || points->HasArcs() )
3613  {
3614  a2dVertexList* lpoints = new a2dVertexList();
3615  *lpoints = *points;
3616  lpoints->ConvertSplinedPolygon( 10 );
3617  rlist = lpoints;
3618  }
3619  else
3620  rlist = points;
3621 
3622  WriteHeader( 0, 0, GDS_BOUNDARY );
3623 
3624  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3625  GDSTYPE_BIT_ARRAY,
3626  GDS_ELFLAGS );
3627 
3628  WriteInt( m_objectFlags );
3629 
3630  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3631  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3632  GDS_LAYER );
3633 
3634  WriteInt( m_mapping[layer] );
3635 
3636  WriteHeader( sizeof( TWO_G_BYTE_SIGNED_INTEGER ),
3637  GDSTYPE_TWO_G_BYTE_SIGNED_INTEGER,
3638  GDS_DATATYPE );
3639 
3640  WriteInt( datatype );
3641 
3642  points->ConvertToLines();
3643  unsigned int n = points->size();
3644 
3645  long help = 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) * ( n + 1 );
3646  if ( help > 65530L )
3647  {
3648  wxLogWarning( wxT( "%s" ), _( "to many points in Polyline" ) );
3649  help = 65530L;
3650  n = help / ( 2 * sizeof( FOUR_G_BYTE_SIGNED_INTEGER ) ) - 1;
3651  }
3652  WriteHeader( help, GDSTYPE_FOUR_G_BYTE_SIGNED_INTEGER, GDS_XY );
3653 
3654  a2dVertexList::iterator iter = points->begin();
3655  double x, y;
3656  unsigned int i = 0;
3657  while ( i < n )
3658  {
3659  a2dPoint2D point = ( *iter )->GetPoint();
3660  lworld.TransformPoint( point.m_x, point.m_y, x, y );
3661  WritePoint( x, y );
3662  iter++;
3663  i++;
3664  }
3665  lworld.TransformPoint( points->front()->m_x, points->front()->m_y, x, y );
3666  WritePoint( x, y );
3667 
3668  WriteHeader( 0, 0, GDS_ENDEL );
3669 
3670  if ( spline || points->HasArcs() )
3671  delete rlist;
3672 }
3673 
3674 // -------------- output -----------------
3675 
3676 // a byte
3677 void a2dIOHandlerGDSOut::WriteByte( G_BYTE ch )
3678 {
3679 #if wxUSE_STD_IOSTREAM
3680  m_streamo->put( ch );
3681 #else
3682  m_streamo->PutC( ch );
3683 #endif
3684 }
3685 
3686 // 2 bytes UNsigned integer
3687 void a2dIOHandlerGDSOut::WriteUnsignedInt( TWO_G_BYTE_UNSIGNED_INTEGER i )
3688 {
3689  a_union_value a_value;
3690  a_value.two_byte_signed_integer = i;
3691 #if wxBYTE_ORDER == wxBIG_ENDIAN
3692  WriteByte( a_value.array.array[0] );
3693  WriteByte( a_value.array.array[1] );
3694 #else
3695  WriteByte( a_value.array.array[1] );
3696  WriteByte( a_value.array.array[0] );
3697 #endif
3698 }
3699 
3700 // 2 bytes signed integer
3701 void a2dIOHandlerGDSOut::WriteInt( TWO_G_BYTE_SIGNED_INTEGER i )
3702 {
3703  a_union_value a_value;
3704  a_value.two_byte_signed_integer = i;
3705 #if wxBYTE_ORDER == wxBIG_ENDIAN
3706  WriteByte( a_value.array.array[0] );
3707  WriteByte( a_value.array.array[1] );
3708 #else
3709  WriteByte( a_value.array.array[1] );
3710  WriteByte( a_value.array.array[0] );
3711 #endif
3712 }
3713 
3714 
3715 // 4 byte signed integer
3716 void a2dIOHandlerGDSOut::WriteLong( FOUR_G_BYTE_SIGNED_INTEGER i )
3717 {
3718  a_union_value a_value;
3719  a_value.four_byte_signed_integer = i;
3720 
3721  // writes a GdsII variable and convers to a dos-variable
3722  // the variable consist of 4 bits, numbered 0 1 2 3 , this
3723  // will be converted to the following sequence: 3 2 1 0
3724 
3725 #if wxBYTE_ORDER == wxBIG_ENDIAN
3726  int t;
3727  for( t = 0; t <= 3; t++ )
3728 #else
3729  int t;
3730  for( t = 3; t >= 0; t-- )
3731 #endif
3732  WriteByte( a_value.array.array[t] );
3733 }
3734 
3735 
3736 // 4 byte byte real
3737 void a2dIOHandlerGDSOut::WriteFloat( FOUR_G_BYTE_REAL r )
3738 {
3739  a_union_value a_value;
3740  a_value.four_byte_real = r;
3741 
3742  // writes a GdsII variable and convers to a dos-variable
3743  // the variable consist of 4 bits, numbered 0 1 2 3 , this
3744  // will be converted to the following sequence: 3 2 1 0
3745 #if wxBYTE_ORDER == wxBIG_ENDIAN
3746  for( short int i = 0; i <= 3; i++ )
3747 #else
3748  for( short int i = 3; i >= 0; i-- )
3749 #endif
3750  WriteByte( a_value.array.array[i] );
3751 }
3752 
3753 
3754 // 8 byte real
3755 void a2dIOHandlerGDSOut::WriteDouble( EIGHT_G_BYTE_REAL r )
3756 {
3757  a_union_value a_value;
3758  a_value.eight_byte_real = r;
3759 
3760  short int i;
3761 
3762  // convers the machine double into GdsII-real
3763  double2gds( a_value.array.array );
3764 
3765  // writes a GdsII variable and convers to a dos-variable
3766  // Reverse ordering will happen in the function gds2double
3767  for( i = 0; i < 8; i++ )
3768  WriteByte( a_value.array.array[i] );
3769 
3770 }
3771 
3772 
3773 #endif //wxART2D_USE_GDSIO
a2dCanvasObject * GetCanvasObject()
Definition: recur.cpp:104
set check on a2dObject flag false or true
Definition: algos.h:665
a2dCircle at x,y, and with radius
Definition: canprim.h:554
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
Definition: afmatrix.cpp:396
a2dPATH_END_TYPE
defines the way a polyline with a contour width is ended.
Definition: polyver.h:31
static const a2dCanvasObjectFlagsMask BIN
Definition: candefs.h:192
void SetBoxType(int type)
GDSII compatible to sub identify types of rectangles.
Definition: canprim.h:498
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
a2dCanvasObjectReference is a reference to any a2dCanvasObject derived class.
Definition: recur.h:53
Quadratic Bezier curve.
Definition: polyver.h:984
virtual void InitializeLoad()
Inits the handler for reading.
Definition: gen.cpp:4971
void SetVersion(wxString version)
set version of library or document
Definition: candoc.h:447
diagram is an appearance for a2dCameleon
Definition: cameleon.h:382
bool GetMultiRoot()
Definition: candoc.h:566
virtual bool IsTemporary_DontSave() const
Check if this is a temporary object, which should not be saved.
Definition: canobj.cpp:6365
void gds2double(unsigned char fb[])
convert a gdsii real to a machine real
Definition: gdsio.cpp:287
virtual wxString GetName() const
Returns the name of this object, if no name is given the internal id will be returned.
Definition: gen.cpp:1310
double m_x2
control point
Definition: polyver.h:1025
void SetUnitsScale(double scale)
this is the number that defines the physical dimension in meters / inch/ etc.
Definition: candoc.h:608
void MakeStrans(const a2dAffineMatrix &matrix)
create an Strans record for GDSII file
Definition: gdsio.cpp:813
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
a2dDrawingId GetDrawingId()
set special id to differentiate drawings
Definition: drawing.h:721
a2dTextGDS text based on wxDC text drawing.
Definition: cantext.h:467
void SetMultiRoot(bool multiRoot=true)
Set true if the document read from a file did not have on erootobject but several.
Definition: candoc.h:563
void ConvertToLines(double aberation=0)
Convert complex segments to line segments.
Definition: polyver.cpp:1948
const int SPLINE_STEP
number of steps when converting a spline to lines.
Definition: artglob.h:334
View on a a2dCanvasDocument.
Definition: candoc.h:212
union Strans::@12 m_stransflags
Strans bit flags for reading and writing to binary file.
unsigned int GetChildObjectsCount() const
get number of child objects
Definition: canobj.cpp:2570
TWO_G_BYTE_UNSIGNED_INTEGER m_recordsize
size of the last read record
Definition: gdsio.h:308
static double GetFontScaleFactor()
a factor to modify the internal text height, compared to the GDSII file height.
Definition: cantext.h:511
virtual void InitializeSave()
Inits the handler for writing.
Definition: gen.cpp:5095
OVERLAP Intersect(const a2dBoundingBox &, double Marge=0) const
Definition: bbox.cpp:205
virtual void ResetSave()
Reset the object after saving.
Definition: gen.cpp:5101
a2dCanvasObject * GetRootObject() const
get the root object, which holds the objects in the document
Definition: drawing.h:521
Cubic Bezier curve.
Definition: polyver.h:1045
double GetContourWidth() const
get the Contour width of the shape
Definition: vpath.h:158
polygon defined with list of points.
Definition: polygon.h:45
void SetTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Returns the matrix used to position the object.
Definition: canobj.h:509
bool Rotate(double angle)
Rotate clockwise by the given number of degrees:
Definition: afmatrix.cpp:432
wxString m_strucname
structure that is being read at the moment
Definition: gdsio.h:330
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
void SkipData()
skip the date of the last read record
Definition: gdsio.cpp:1217
wxOutputStream a2dDocumentOutputStream
output stream based wxStreams
Definition: gen.h:3458
double m_y2
control point
Definition: polyver.h:1027
double m_y3
control point 2
Definition: polyver.h:1100
double GetUnitsScale()
this is the number that defines the physical dimension in meters / inch/ etc.
Definition: candoc.h:601
a2dDocumentInputStream * m_streami
file or other string stream containing the format to parse.
Definition: gen.h:3734
Arc Segment.
Definition: polyver.h:1112
a2dCanvasDocument * m_doc
the document to store/load the data found into
Definition: gdsio.h:320
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
double m_x3
control point 2
Definition: polyver.h:1098
double GetValue(int col, int row) const
get the value in the matrix at col,row
Definition: afmatrix.cpp:106
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: artglob.cpp:34
a2dDrawing * GetDrawing() const
get the root object, which holds the objects in the document.
Definition: candoc.h:418
a2dRectC is a centered rectangle
Definition: canprim.h:99
int GetDataType()
GDSII compatible to sub identify this object.
Definition: vpath.h:166
The base class for all drawable objects in a a2dCanvasDocument.
void SetLibraryName(const wxString &libraryname)
to name the document as a library (independent of a path and filename )
Definition: candoc.h:441
a2dVertexList * ConvertSplinedPolyline(double Aber) const
Spline conversion for polyline.
Definition: polyver.cpp:2858
virtual bool Save(a2dDocumentOutputStream &stream, const wxObject *doc)
Override to write to the stream and store (part of) of the document contents in the stream...
Definition: gdsio.cpp:2199
vertex array of line and arc segments.
Definition: polyver.h:494
bool m_textAsPath
if true, convert text to a2dVpath
Definition: gdsio.h:473
object to show several appearance views on what it contains
Definition: cameleon.h:630
void SetDrawingId(a2dDrawingId id)
get special id to differentiate drawings
Definition: drawing.h:723
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
std::vector< a2dLayerInfoPtr > & GetLayerIndex()
return array index on Layer
Definition: layerinf.cpp:555
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
double m_y2
control point 1
Definition: polyver.h:1095
Docview framework its controlling class.
a2dCanvasObjectArrayReference is an array of a reference to any a2dCanvasObject derived class...
Definition: recur.h:131
Holds an error message.
a2dPATHSEG_END GetClose() const
is this segment the closing a part since the last move
Definition: polyver.h:910
a2dLayers * GetLayerSetup()
Get the layersettings for the canvas.
Definition: candoc.h:555
void SetWidth(double w)
set width of rectangle
Definition: canprim.h:328
a2dLayers * GetLayerSetup()
Get the layersettings for the canvas.
Definition: drawing.h:506
std::vector< int > m_mapping
mapping of GDSII layers to internal layers
Definition: gdsio.h:317
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
vertex list of line and arc segments.
Definition: polyver.h:600
a2dPATH_END_TYPE GetPathType()
get when m_contourwidth != 0 what is the end of the lines looks like.
Definition: vpath.h:172
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
defenitions an no more
special a2dCanvasObject which are used to create hierarchy different from the standard a2dCanvasObjec...
virtual void SetName(const wxString &name)
Creates the a2dStringProperty PROPID_Name.
Definition: gen.cpp:1305
store and convert number to number with unit and visa versa. e.g. 1.23e-6 =&gt; 1.23 * 1e-6 ...
Definition: artglob.h:208
a2dPATH_END_TYPE GetPathType()
get when m_contourwidth != 0 what is the end of the line looks like.
Definition: polygon.h:404
void SetBin(bool bin)
general flag use at will.
Definition: canobj.h:2259
void SetUnitsAccuracy(double accuracy)
this is the number that defines the number of decimal places in the fraction
Definition: candoc.h:595
bool m_back
last read record is stored
Definition: gdsio.h:305
void SetContourWidth(double width)
set the Contour width of the shape
Definition: polygon.h:237
a2dVertexList * ConvertSplinedPolygon(double Aber) const
Spline conversion for polygon.
Definition: polyver.cpp:2846
void AddToRoot(bool autoPlace=true)
add this to ms_centralCameleonRoot at a suitable position
Definition: cameleon.cpp:1260
vector path a2dVectorPath derived from a2dCanvasObject
GDSII format input and output.
Definition: gdserr.h:23
void double2gds(unsigned char fb[])
convert a machine real to a gdsii real
Definition: gdsio.cpp:488
a2dIOHandlerStrIn & SeekI(wxFileOffset pos)
set stream at a position
Definition: gen.cpp:5021
void SetHeight(double h)
set height of rectangle
Definition: canprim.h:334
bool GetCheck() const
general flag use at will.
Definition: gen.h:1342
void WriteString(const wxString &a_string)
write a string
Definition: gdsio.cpp:3053
void SetRootRecursive()
set a2dDrawing to its nested a2dCanvasObject&#39;s recursive for whole tree
Definition: drawing.cpp:913
a2dText is an abstract base class.
Definition: cantext.h:93
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the line should be.
Definition: polygon.h:401
wxUint16 GetTextType()
GDSII compatible to sub identify types of rectangles.
Definition: cantext.h:497
bool HasArcs() const
return true if there are a2dArcSegment segments.
Definition: polyver.cpp:1761
wxString GetVersion()
get version of library or document
Definition: candoc.h:450
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual bool CanLoad(a2dDocumentInputStream &stream, const wxObject *obj=NULL, wxClassInfo *docClassInfo=NULL)
Should return true if the handler can read from the stream.
Definition: gdsio.cpp:902
a2dCameleon * GetCameleon()
this appearance is for the returned a2dCameleon here.
Definition: cameleon.h:229
bool ReadHeader(int type)
Definition: gdsio.cpp:1184
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
bool CanSave(const wxObject *obj=NULL)
Should return true if the handler can write this document to a stream.
Definition: gdsio.cpp:2181
virtual void InitializeSave()
Inits the handler for writing.
Definition: gdsio.cpp:2188
a2dEllipse centered at x,y.
Definition: canprim.h:635
polyline defined with list of points.
Definition: polygon.h:332
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
a2dCameleonInst to show one appearance of an a2dCameleon.
Definition: cameleon.h:272
virtual bool Load(a2dDocumentInputStream &stream, wxObject *doc)
override to read the stream and store (part of) the contents in to a specific a2dDocument or othere o...
Definition: gdsio.cpp:951
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
layer settings for a a2dCanvasDocument Holds layers settings classes
void SetTextType(wxUint16 type)
GDSII compatible to sub identify types of rectangles.
Definition: cantext.h:493
Definition: bbox.h:26
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
G_BYTE m_datatype
the type of the data in the last read record
Definition: gdsio.h:314
a2dSLine
Definition: canprim.h:987
bool CalcR(a2dVpathSegmentPtr prev, double &radius, double &center_x, double &center_y, double &beginrad, double &midrad, double &endrad, double &phit)
Calculation of center for the Arc.
Definition: polyver.cpp:3820
a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
return text as a vector path, where text outline is converted to polyline or polygons.
Definition: cantext.cpp:247
wxUint16 GetLayer() const
Returns the layer index where this object is drawn upon.
Definition: canobj.h:2368
int CollectObjects(a2dCanvasObjectList *total, const wxString &type=wxT(""), a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const a2dPropertyId *id=NULL, const a2dBoundingBox &bbox=wxNonValidBbox)
Copy objects fitting the given filter to the total list.
Definition: objlist.cpp:663
void SetMin(double px, double py)
set the bounding box its maximum
Definition: bbox.cpp:340
bool GetBin() const
general flag use at will.
Definition: canobj.h:2262
for reading bytes from a binary GDS-II file, and convert them to internal types.
Definition: gdsio.cpp:104
double GetTextHeight() const
get text height in world coordinates
Definition: cantext.h:176
Tappear * GetAppearance(bool autoCreate=false)
Get a specific a2dAppear derived class instance from here.
Definition: cameleon.h:666
bool GetSpline()
Get the polygon spline setting.
Definition: polygon.h:235
a2dArrow is used for having line begin and ends on specific objects.
Definition: canprim.h:198
a2dHashMapIntToObject & GetObjectHashMap()
This is used to find multiple referenced objects by id.
Definition: gen.h:3479
set a2dCanvasObjects flags in a hierarchy of a a2dCanvasDocument
Definition: algos.h:486
wxDateTime & GetModificationTime()
Returns the time of last modification when the document was saved.
Definition: docviewref.h:1410
wxFileName GetFilename() const
Get the file name in use for this document.
Definition: docviewref.h:1103
double m_x2
control point 1
Definition: polyver.h:1093
double GetContourWidth() const
get the Contour width of the shape
Definition: polygon.h:240
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
a2dCanvasDocument * m_doc
the document to store/load the data found into
Definition: gdsio.h:464
a2dView * GetCurrentView() const
return the one that is active right now (e.g. has focus in case of a wxWindow), or NULL ...
Definition: doccom.cpp:1185
wxClassInfo * m_docClassInfo
Run-time class information that allows document instances to be constructed dynamically.
Definition: gen.h:3737
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
double GetPosY() const
get y position from affine matrix
Definition: canobj.h:530
bool LoadLayers(const wxString &filename)
load layers from another file
Definition: candoc.cpp:1010
void Aberration(double angle, double radius, double &dphi, unsigned int &segments)
based on angle and radius and m_displayaberration calculate a proper delta phi and number of segments...
Definition: artglob.cpp:154
void SetMax(double px, double py)
set the bounding box its minimum
Definition: bbox.cpp:352
std::vector< int > m_mapping
mapping of GDSII layers to internal layers
Definition: gdsio.h:461
wxInputStream a2dDocumentInputStream
input stream based wxStreams
Definition: gen.h:3456
double m_x
x endpoint of line
Definition: polyver.h:232
polygon defined with list of points for outer contour plus a list of hole polygons ...
Definition: polygon.h:502
a2dWalker based algorithms
a2dLineSegment * AddPoint(double x, double y, a2dLineSegmentPtr seg=NULL, bool afterinversion=true)
add point/segment after a segment.
Definition: polygon.cpp:356
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:546
a_union_value()
constructor reset it to 0&#39;s
Definition: gdsio.cpp:107
special a2dCanvasObject to make a multi view hierachy.
double m_y
y endpoint of line
Definition: polyver.h:235
a2dDocviewGlobal * a2dDocviewGlobals
a global pointer to get to global instance of important classes.
Definition: doccom.cpp:2348
a2dPATHSEG GetType() const
easy way to test type of segment
Definition: polyver.h:901
double GetUnitsAccuracy()
this is the number that defines the number of decimal places in the fraction
Definition: candoc.h:586
Each a2dCanvasView needs to have a a2dCanvasDocument set in order to render data. ...
Definition: candoc.h:374
bool GetRelease() const
get release flag
Definition: gen.h:1350
void SetAberPolyToArc(const a2dDoMu &aber)
Polygon/polyline to Arc Maximum abberation.
Definition: canglob.cpp:815
double m_y1
y endpoint of line
Definition: polyver.h:922
class to hold GDS-II transformation info, only used within the GDSII reader
Definition: gdsio.h:168
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
wxString GetMultiplierString() const
get the number 1.1 um -&gt; &quot;um&quot;
Definition: artglob.cpp:353
void SetUnits(const wxString &unitString)
this string defines the unit e.g. meters / inch/ etc.
Definition: candoc.h:643
a2dAppear * GetAppearance()
get referenced a2dCameleon
Definition: cameleon.h:293
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
Definition: afmatrix.cpp:270
bool Start(a2dCanvasObject *object, bool setTo)
start removing properties from the object given, and down.
Definition: algos.cpp:784
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
virtual void ReportErrorF(const a2dError &error, const wxChar *Format,...)
concatenate to the the error report the given error.
Definition: comevt.cpp:1312
G_BYTE m_recordtype
recordtype of last read record
Definition: gdsio.h:311
Definition: gdsio.cpp:270
const a2dError a2dError_NotSpecified
a2dDocumentCommandProcessor * GetDocviewCommandProcessor() const
Gets a2dDocumentCommandProcessor pointer.
Definition: doccom.h:1034
a2dRect
Definition: canprim.h:440
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
virtual void ResetLoad()
Reset the handler after loading.
Definition: gdsio.cpp:897
void SetLayerSetup(a2dLayers *layersetup)
set the layersettings for the canvas.
Definition: drawing.cpp:280
array of bytes, which holds a string in GDS-II
Definition: gdsio.cpp:94
virtual void ReportWarningF(const a2dError &error, const wxChar *Format,...)
concatenate to the error report the given warning.
Definition: comevt.cpp:1325
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
double Check_int(double getal)
ckecking of it is near enough to a integer number
Definition: gdsio.cpp:694
a2dArc centered at x,y
Definition: canprim.h:823
the a2dDrawingPart is a a2dView specially designed for displaying parts of a a2dDrawing. It uses a a2dDrawer2D to actually redraw things from the document, by giving that a2dDrawer2D as drawing context to the document, and telling the document to redraw a certain rectangular area. At that last is what this class is for. It optimizes the areas to be redrawn after object in the document were changed. To do that it combines redraw areas to a minimal set of redrawing areas. All the administration for this and the way things will be redrawn is from this view.
Strans(double nw_angle=DEFAULT_STRANS_ANGLE, double nw_scale=DEFAULT_STRANS_SCALE, bool nw_abs_angle=DEFAULT_STRANS_ABS_ANGLE, bool nw_abs_scale=DEFAULT_STRANS_ABS_SCALE, bool nw_reflection=DEFAULT_STRANS_REFLECTION)
constructor
Definition: gdsio.cpp:716
double m_x1
x endpoint of line
Definition: polyver.h:919
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
a2dVpath * GetSegments()
modify point at index to x,y
Definition: vpath.h:117
virtual void ResetSave()
Reset the object after saving.
Definition: gdsio.cpp:2194
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
#define Round(x)
round to integer such that e.g 2.5 &lt; x &lt; 3.5 becomes 3
Definition: artglob.h:60
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
virtual void InitializeLoad()
Inits the handler for reading.
Definition: gdsio.cpp:890
holds one error report.
Definition: gen.h:623
Vector Path.
Definition: polyver.h:1211
const a2dDoMu & GetAberPolyToArc() const
Polygon/polyline to Arc Maximum abberation.
Definition: canglob.h:727
static void SetCameleonRoot(a2dCanvasObject *cameleonRoot)
set the root where all a2dCameleon&#39;s are stored
Definition: cameleon.h:714
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
wxDateTime & GetAccessTime()
Returns the time of last access.
Definition: candoc.h:652
static a2dPropertyIdUint16 * PROPID_Datatype
used in GDSII and KEY format to specify the DATATYPE of elements
Definition: canobj.h:2700
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
GdsII format input and output.
wxString GetText() const
get the text of the object &#39; &#39; in string means new line
Definition: cantext.h:168
void SetShowObject(a2dCanvasObject *show)
what to display when document is openened
Definition: candoc.h:576
void ConvertToLines(double aberation=0)
Convert complex segments to line segments.
Definition: polyver.cpp:867
void SetTopCameleon(a2dCameleon *root)
what is the top a2dcameleon in the drawing to display after opening a document, when m_show is not se...
Definition: candoc.h:571
virtual bool LinkReferences(bool ignoreNonResolved=false)
link references to their destination
Definition: gen.cpp:4862
a2dDocumentOutputStream * m_streamo
file or other string stream containing the format to output to.
Definition: gen.h:3825
void ReadString(wxString &a_string)
read string data for Text element, structure names etc.
Definition: gdsio.cpp:1230
virtual void ResetLoad()
Reset the handler after loading.
Definition: gen.cpp:4977
bool ResolveOrAddLink(a2dObject *obj, const wxString &id=wxT(""))
try to resolve an object referenced by obj using the LinkReference function
Definition: gen.cpp:4808
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
wxString & GetLibraryName()
Get name the document as a library (independent of a path and filename )
Definition: candoc.h:444
const double wxPI
defines PI
Definition: artglob.cpp:28
a2dEllipticArc centered at x,y
Definition: canprim.h:697
const a2dError a2dError_GDSIIparse
general canvas module declarations and classes
gdsio.cpp Source File -- Sun Oct 12 2014 17:04:20 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation